对于停用词以及未切分的词的处理方法:过滤掉CHAR_USELESS字符,包括标点以及无法识别的字符,pathMap中存储的是lexemePath集合,找出相邻的lexemePath,把它们之间未切分的字符逐字符输出,原来的ik源码里面有processUnkownCJKChar(),在IK2012中,这个方法被合并到了outputToResult(),
//对分词进行歧义处理
this.arbitrator.process(context,this.cfg.useSmart());
//将分词结果输出到结果集,并处理未切分的单个CJK字符
context.outputToResult();
//记录本次分词的缓冲区位移
context.markBufferOffset();
/**
* 推送分词结果到结果集合
* 1.从buff头部遍历到this.cursor已处理位置
* 2.将map中存在的分词结果推入results
* 3.将map中不存在的CJDK字符以单字方式推入results
*/
void outputToResult(){
int index = 0;
for( ; index <=this.cursor ;){
//跳过非CJK字符
if(CharacterUtil.CHAR_USELESS ==this.charTypes[index]){
index++;
continue;
}
//从pathMap找出对应index位置的LexemePath
LexemePath path = this.pathMap.get(index);
if(path !=null){
//输出LexemePath中的lexeme到results集合
Lexeme l = path.pollFirst();
while(l !=null){
this.results.add(l);
//将index移至lexeme后
index= l.getBegin() + l.getLength();
l= path.pollFirst();
if(l !=null){
//输出path内部,词元间遗漏的单字
for(;index <l.getBegin();index++){
this.outputSingleCJK(index);
}
}
}
}else{//pathMap中找不到index对应的LexemePath
//单字输出
this.outputSingleCJK(index);
index++;
}
}
//清空当前的Map
this.pathMap.clear();
}
在词代码中有个方法 outputStringCJK(index)便是将没有切分的单字进行输出。
最后看看对停用词的处理
/**
* 返回lexeme
*
* 同时处理合并
* @return
*/
Lexeme getNextLexeme(){
//从结果集取出,并移除第一个Lexme
Lexeme result = this.results.pollFirst();
while(result !=null){
//数量词合并
this.compound(result);
if(Dictionary.getSingleton().isStopWord(this.segmentBuff , result.getBegin() , result.getLength())){
//是停止词继续取列表的下一个
result = this.results.pollFirst();
}else{
//不是停止词,生成lexeme的词元文本,输出
result.setLexemeText(String.valueOf(segmentBuff , result.getBegin() ,result.getLength()));
break;
}
}
return result;
}
在此方法中有个isStopWord ,这个方法是用来判断这个词是否为停用词,如果是停用词便继续取列表的下一个再来进行处理。这个过程中一边切词一边判断是否为停用词,可以通过调试看的更清楚些。
源码地址:http://download.csdn.net/detail/a925907195/8240641