lindera_trainer/
corpus.rs1use std::io::{BufRead, BufReader, Read};
2
3use anyhow::Result;
4
5pub struct Word {
7 surface: String,
8 feature: String,
9}
10
11impl Word {
12 pub fn new(surface: &str, feature: &str) -> Self {
13 Self {
14 surface: surface.to_string(),
15 feature: feature.to_string(),
16 }
17 }
18
19 pub fn surface(&self) -> &str {
21 &self.surface
22 }
23
24 pub fn feature(&self) -> &str {
26 &self.feature
27 }
28}
29
30pub struct Example {
32 pub(crate) sentence: String,
33 pub(crate) tokens: Vec<Word>,
34}
35
36impl Example {
37 pub fn new(tokens: Vec<Word>) -> Self {
39 let sentence = tokens.iter().map(|t| t.surface()).collect::<String>();
40 Self { sentence, tokens }
41 }
42}
43
44pub struct Corpus {
46 pub(crate) examples: Vec<Example>,
47}
48
49impl Default for Corpus {
50 fn default() -> Self {
51 Self::new()
52 }
53}
54
55impl Corpus {
56 pub fn new() -> Self {
58 Self {
59 examples: Vec::new(),
60 }
61 }
62
63 pub fn from_reader<R: Read>(reader: R) -> Result<Self> {
69 let reader = BufReader::new(reader);
70 let mut corpus = Self::new();
71 let mut current_tokens = Vec::new();
72
73 for line in reader.lines() {
74 let line = line?;
75
76 if line.trim().is_empty() || line == "EOS" {
77 if !current_tokens.is_empty() {
79 corpus.examples.push(Example::new(current_tokens));
80 current_tokens = Vec::new();
81 }
82 } else {
83 let parts: Vec<&str> = line.split('\t').collect();
85 if parts.len() >= 2 {
86 let surface = parts[0];
87 let features = parts[1];
88 current_tokens.push(Word::new(surface, features));
89 }
90 }
91 }
92
93 if !current_tokens.is_empty() {
95 corpus.examples.push(Example::new(current_tokens));
96 }
97
98 Ok(corpus)
99 }
100
101 pub fn len(&self) -> usize {
103 self.examples.len()
104 }
105
106 pub fn is_empty(&self) -> bool {
108 self.examples.is_empty()
109 }
110}
111
112#[cfg(test)]
113mod tests {
114 use super::*;
115 use std::io::Cursor;
116
117 #[test]
118 fn test_corpus_from_reader() {
119 let corpus_data = r#"外国 名詞,一般,*,*,*,*,外国,ガイコク,ガイコク
120人 名詞,接尾,一般,*,*,*,人,ジン,ジン
121EOS
122
123これ 連体詞,*,*,*,*,*,これ,コレ,コレ
124は 助詞,係助詞,*,*,*,*,は,ハ,ワ
125EOS
126"#;
127
128 let cursor = Cursor::new(corpus_data.as_bytes());
129 let corpus = Corpus::from_reader(cursor).unwrap();
130
131 assert_eq!(corpus.len(), 2);
132 }
135}