use lindera::tokenizer::Tokenizer;
use lindera::mode::Mode;
use lindera_core::viterbi::{PenaltyType};
use anyhow::Result;
pub struct JapaneseTokenizer {
tokenizer: Tokenizer,
}
impl JapaneseTokenizer {
pub fn new() -> Result<Self> {
// IPADIC 辞書を使用したトークナイザーの初期化
// 辞書は埋め込みバイナリとして扱われる
let tokenizer = Tokenizer::new_with_config(lindera::tokenizer::TokenizerConfig {
dictionary: lindera::tokenizer::DictionaryConfig {
kind: Some(lindera_core::lexicon::DictionaryKind::IPADIC),
path: None,
},
user_dictionary: None,
mode: Mode::Decompose(Mode::Normal), // 検索向けに分解モード
})?;
Ok(JapaneseTokenizer { tokenizer })
}
/// テキストを形態素解析し、わかち書き(スペース区切り)の文字列として返す
pub fn tokenize_to_string(&self, text: &str) -> Result<String> {
let tokens = self.tokenizer.tokenize(text)?;
let result: Vec<&str> = tokens
.iter()
.map(|token| token.text)
.collect();
Ok(result.join(" "))
}
/// 単語のリスト(ベクタ)として返す
pub fn tokenize_to_vec(&self, text: &str) -> Result<Vec<String>> {
let tokens = self.tokenizer.tokenize(text)?;
Ok(tokens.iter().map(|t| t.text.to_string()).collect())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_japanese_tokenization() {
let tokenizer = JapaneseTokenizer::new().unwrap();
let text = "すもももももももものうち";
let tokenized = tokenizer.tokenize_to_string(text).unwrap();
assert!(tokenized.contains("すもも"));
assert!(tokenized.contains("もも"));
}
}