引言
最近項目中可能有個需求需要用到分詞,所以研究了解了一下Java的ansj子姜,然后發(fā)現(xiàn)了個數(shù)字與英文量詞一直被分隔出來的問題
場景復(fù)現(xiàn)
根據(jù)官方文檔祟绊,通過配置文件的
isQuantifierRecognition
字段可以開啟數(shù)字和量詞合并public class MyStaticValue { // 是否數(shù)字和量詞合并 public static Boolean isQuantifierRecognition = true;
通過源碼可知,該變量已默認(rèn)為true
實際測試效果
String text = "這是一條100厘米的繩子";
System.out.println(ToAnalysis.parse(text));
String text2 = "這是一條100cm的繩子";
System.out.println(ToAnalysis.parse(text2));
輸出結(jié)果
這/r,是/v,一條/mq,100厘米/mq,的/u,繩子/n
這/r,是/v,一條/mq,100/m,cm/en,的/u,繩子/n
可以見到哥捕,開啟數(shù)字和量詞合并后牧抽,對于數(shù)字與中文量詞組合的可以成功分割,但對于數(shù)字與英文量詞組合的無法正確切分
問題排查
通過查閱文檔和源碼可知遥赚,量詞詞性使用q_mq
扬舒,于是一開始思路考慮手動添加自定義詞
DicLibrary.insert(DicLibrary.DEFAULT, "cm", "q_mq", DicLibrary.DEFAULT_FREQ);
但是經(jīng)實驗并沒有生效,然后開始跟蹤源碼凫佛,發(fā)現(xiàn)isQuantifierRecognition
變量開啟后讲坎,主要是通過一個結(jié)果處理器NumRecognition
對結(jié)果進行數(shù)字量詞合并,
于是一路跟蹤進去愧薛,查看這個Recognition的源碼
發(fā)現(xiàn)主要邏輯是根據(jù)這個
isQua
來決定是否將兩個詞合并晨炕,然后我們來看一下剛那個cm量詞的isQua
,可以發(fā)現(xiàn)即使我們將cm添加為自定義量詞,這個變量也仍為false毫炉,于是再跟蹤這個變量的賦值過程瓮栗,
發(fā)現(xiàn)只有initValue的時候才會將內(nèi)置的量詞
NumNatureAttr
的isQua
字段置為true,后續(xù)添加的不會再走這段邏輯瞄勾,所以也解釋了為什么不生效的問題
解決方法
- 修改源碼的core.dic生成文件费奸,將要添加的量詞直接生成進去
- 自己手寫一個Recognition對結(jié)果進行處理
因為項目的需求不光是要將100cm
合并,對于如DN25
也需合并进陡,所以我就直接采用第二種方法愿阐,將數(shù)字英文直接合并在一起了
這里也簡單貼一下自己寫的Recognition代碼
public class SpecificationWordRecognition implements Recognition {
private static final Nature SPECIFICATION_NATURE = new Nature("specification");
@Override
public void recognition(Result result) {
List<Term> terms = result.getTerms();
for (Term term : terms) {
if (term.getName() == null) {
continue;
}
if ("m".equals(term.getNatureStr()) || "en".equals(term.getNatureStr())) {
Term to = term.to();
while ("m".equals(to.getNatureStr()) || "en".equals(to.getNatureStr())) {
term.merage(to);
to.setName(null);
term.setNature(SPECIFICATION_NATURE);
to = to.to();
}
}
}
for (Iterator<Term> iterator = terms.iterator(); iterator.hasNext();) {
Term term = iterator.next();
if (term.getName() == null) {
iterator.remove();
}
}
}
}