Exemplo n.º 1
0
        /// <summary>
        /// 快速原子分词,将连续的同类型的字符作为一个AtomNode
        /// 对浮点数做了特殊处理
        /// </summary>
        /// <param name="chars"></param>
        /// <param name="start">起始位置,inclusive</param>
        /// <param name="end">截止位置,exclusive</param>
        /// <returns></returns>
        protected static List <AtomNode> QuickAtomSegment(char[] chars, int start, int end)
        {
            var atoms   = new List <AtomNode>();
            var cursor  = start;
            int preType = CharType.Get(chars[cursor++]);            // 获取首个字符类型
            int curType;

            while (cursor < end)                                     // 从第二个字符开始,将连续类型的字符组成的字符串作为一个整体,构建一个原子节点对象
            {
                curType = CharType.Get(chars[cursor]);
                if (curType != preType)                             // 如果收到前后相邻字符的类型不一致
                {
                    if (chars[cursor] == '.' && preType == CT_NUM)  // 浮点数识别
                    {
                        cursor++;                                   // 指向 dot 符号的下一个符号
                        while (cursor < end)
                        {
                            curType = CharType.Get(chars[cursor]);  // 获取符号类型
                            if (curType != CT_NUM)
                            {
                                break;                              // 类型不一致,退出循环
                            }
                            cursor++;
                        }
                    }
                    atoms.Add(new AtomNode(new string(chars, start, cursor - start), preType));     //
                    start = cursor;
                }
                preType = curType; // 更新当前字符的类型
                cursor++;          // 更新指针指向下一个字符
            }
            if (cursor == end)     // 还有一种可能就是cursor= end + 1,这种情况时最后末尾为一个浮点数,已经加入列表
            {
                atoms.Add(new AtomNode(new string(chars, start, end - start), preType));
            }
            return(atoms);
        }
Exemplo n.º 2
0
        /// <summary>
        /// 原子分词
        /// 仅对数字以及单字节字符连接处理为一个AtomNode,其他每个字符自成一个AtomNode
        /// 考虑了浮点数
        /// </summary>
        /// <param name="chars">待分词字符数组</param>
        /// <param name="start">起始点 inclusive</param>
        /// <param name="end">截止点 exclusive</param>
        /// <returns></returns>
        protected static List <AtomNode> AtomSegment(char[] chars, int start, int end)
        {
            var atoms = new List <AtomNode>();
            var sb    = new StringBuilder();

            char c;
            var  charTypeArr = new int[end - start];    // 创建用于保存字符类型的数组

            for (int i = 0; i < charTypeArr.Length; i++)
            {
                c = chars[i + start];                   // 当前字符
                charTypeArr[i] = CharType.Get(c);       // 当前字符的类型

                //! 对几种特殊情况作类型调整
                if (c == '.' && i + start < (chars.Length - 1) && CharType.Get(chars[i + start + 1]) == CT_NUM)   // 如果当前是 dot,并且后面跟的字符是数字类型,则标记当前位置类型为数字类型
                {
                    charTypeArr[i] = CT_NUM;
                }
                //else if (c == '.' && i + start < (chars.Length - 1) && chars[i + start + 1] >= '0' && chars[i + start + 1] <= '9')      //todo: 这个条件不是跟上面一样吗?
                //    charTypeArr[i] = CT_SINGLE;
                else if (charTypeArr[i] == CT_LETTER)   // 如果为字母类型,则先统一改成 “单字节” 字符类型
                {
                    charTypeArr[i] = CT_SINGLE;
                }
            }

            int cursor = start;
            int curType, nextType;

            // 对每个字符以及字符类型,构建一个原子节点对象并添加到列表。只有遇到连续数字类型时,将连续的表示数字(integer or float)的字符串作为一个整体原子节点
            while (cursor < end)
            {
                curType = charTypeArr[cursor - start];      // 当前字符类型

                if (curType == CT_CHINESE || curType == CT_INDEX || curType == CT_DELIMITER || curType == CT_OTHER)
                {
                    atoms.Add(new AtomNode(chars[cursor], curType));
                    cursor++;
                }
                //! 遇到连续的单字节字符,或者连续的“数字” 类型的字符,则将这些连续的相同类型字符的字符串作为一个整体,构建原子节点对象
                else if (cursor < end - 1 && (curType == CT_SINGLE || curType == CT_NUM))
                {
                    sb.Clear();
                    sb.Append(chars[cursor]);                     // 将当前数字/单字节 字符添加到缓冲区

                    bool used = true;                             // 当前指针指向的字符是否被使用
                    while (cursor < end - 1)                      // 尚未达到最后一个字符
                    {
                        nextType = charTypeArr[++cursor - start]; // 下一个字符类型,并将指针指向下一个字符
                        if (nextType == curType)
                        {
                            sb.Append(chars[cursor]);
                        }
                        else
                        {
                            used = false;
                            break;
                        }
                    }
                    atoms.Add(new AtomNode(sb.ToString(), curType));
                    if (used)     // 如果当前指针指向字符 已经被使用,cursor 需要 增 1
                    {
                        cursor++; //
                    }
                }
                else
                {
                    atoms.Add(new AtomNode(chars[cursor], curType));
                    cursor++;
                }
            }
            return(atoms);
        }