zoukankan      html  css  js  c++  java
  • 开源搜索框架Lucene学习之分词器(2)——TokenFilter类及其子类

          前面我们分析了一下Tokenizer类及它的子类,Tokenizer类继承于TokenStream类,它的作用主要是把一个字符串分隔成一个个的词,不同的子类实现不同的切分方式。有按空格的,有按非英文字符的。把切分出来的词Token组合成TokenStream。今天我们要讨论的是TokenFilter及其子类。TokenFilter类也是继承于TokenSteam类,它的作用是对分出来的词进行一些处理,比如去掉停词,转换大小写。我们来看TokenFilter类的代码:

    abstract public class TokenFilter : TokenStream
    {
        ///<summary>
        ///需要传过来的处理的TokenStream
        ///The source of tokens for this filter. 
        ///</summary>
        protected TokenStream input;
     
        ///<summary> Close the input TokenStream. </summary>
        public override void Close()
        {
            input.Close();
        }
     
    }

         也是一个抽象类,它里面定义了一个受保护的成员TokenStream类型的input,我们知道在Tokenizer类里面定义了一个受保护的TextReader类型的input,Tokenizer类里面接收的是一个文本流,而TokenFilter类则需要接收一个TokenStream,也就是一个语汇单元流。具体的流程就是把一个字符串传递给Tokenizer,Tokenizer把这个字符串分拆成一个个的Token,然后把这些Token组合成一个TokenStream,也就是一个语汇单元流,然后把这个语汇单元流传给TokenFilter,TokenFilter会对TokenStream里面的每一个Token进行一下处理。根据处理方式的不同,由不同的子类来实现这些处理方式。先来看看第一个子类LowerCaseFilter,也就是把每个Token都转换成小写的。

    public class LowerCaseFilter : TokenFilter
    {
        /// <summary>
        /// Initializes a new instance of the LowerCaseFilter class.
        /// </summary>
        /// <param name="ts">Token stream to read from.</param>
        public LowerCaseFilter(TokenStream ts)
        {
            input = ts;
        }
     
        /// <summary>
        /// Returns the next token from the stream.
        /// </summary>
        /// <returns>The next token or null if EOS.</returns>
        public override Token Next()
        {
            Token t = input.Next();
     
            if (t == null)
                return null;
     
            t.TermText = t.TermText.ToLower();
     
            return t;
        }
    }

         主要就是Next方法,里面就是把每一个Token转换成小写。方法比较简单,就不用解释了。再看第二个子类,去掉停词的类StopFilter,我们就只看Next方法,代码如下:

    public override Token Next()
    {
        // return the first non-stop word found
        for (Token token = input.Next(); token != null; token = input.Next())
            if (table[token.TermText] == null)
                return token;
        // reached EOS -- return null
        return null;
    }

         这个方法里面有一个table变量,它是一个HashTable的对象,里面装的就是停词,也就是那些没有实际意义,需要剔除的词,这个停词集合,在这个类里面有一个初始化,也就是英文中常用的停词集合,你也可以自己传入一个停词的集合。Next方法主要就是遍历每一个Token,看其是否是停词,如果是的,就去掉。

         接下来要看的一个子类就比较有意思,它的作用就是把词元进行一些Stem处理,Stem就是把每一个词元还原成原型,比如cars转换成car。这里会用到一个著名的的stemming算法,全称是The Porter Stemming Algorithm,其主页为http://tartarus.org/~martin/PorterStemmer/,也可查看其论文http://tartarus.org/~martin/PorterStemmer/def.txt。通过以下网页可以进行简单的测试:Porter's Stemming Algorithm Online[http://facweb.cs.depaul.edu/mobasher/classes/csc575/porter.html]。比如cars –> car,driving –> drive,tokenization –> token。下面我们来看看这个类的Next方法:

    public override Token Next()
    {
        Token token = input.Next();
        if (token == null)
            return null;
        else
        {
            String s = stemmer.stem(token.TermText);
            if (s != token.TermText) // Yes, I mean object reference comparison here
                token.TermText = s;
            return token;
        }
    }

        当然首先是定义了一个封装了stemming算法的类PorterStemmer的对象stemmer,然后调用这个里面的stem方法,把每一个Token都处理一下,返回即可。有时间的话把stemming算法单独拿出来解读一下。

        分词的一些基本类都已经介绍完成了,前面所介绍的都是一些简单的分词,Lucene里面内置了四个分词器,分别是WhitespaceAnalyzer,SimpleAnalyzer,StopAnalyzer还有一个StandardAnalyzer分词器,前三个分词器用前面介绍的一些类就可以完成其功能,StandardAnalyzer分词器比较复杂,下次将来解读,构成StandardAnalyzer分词器的StandardFilter类和StandardTokenizer类。

  • 相关阅读:
    SPOJ GSS1 ~ 8解题报告 【完整版】
    题解 UVA1659 【帮助小罗拉 Help Little Laura】
    题解 UVA753 【UNIX插头 A Plug for UNIX】
    题解 P3740 【[HAOI2014]贴海报】
    对拍程序
    dut新生大礼包3
    1240C
    DISCO Presents Discovery Channel Code Contest 2020 Qual 题解
    1254C
    1285E
  • 原文地址:https://www.cnblogs.com/xiaoxiangfeizi/p/2307357.html
Copyright © 2011-2022 走看看