/// <summary> /// 原子分词,连续的数字或连续的英文字母整体作为一格词,其他单个字符自成一词 /// 没有标记词性 /// </summary> /// <param name="sentence"></param> /// <returns></returns> public static List <string> AtomSeg(char[] sentence) { var list = new List <string>(sentence.Length); var lastIdx = sentence.Length - 1; // 最后一个字符的下标 var sb = new StringBuilder(); // 缓存连续的数字,或连续的英文字母 char c; for (int i = 0; i < sentence.Length; i++) { c = sentence[i]; if (c >= '0' && c <= '9') { sb.Append(c); if (i == lastIdx) { list.Add(sb.ToString()); sb.Clear(); break; } c = sentence[++i]; while (c == '.' || c == '%' || (c >= '0' && c <= '9')) // 检查是否有连续的数字 { sb.Append(c); if (i == lastIdx) { list.Add(sb.ToString()); sb.Clear(); goto FINISH; } c = sentence[++i]; } list.Add(sb.ToString()); sb.Clear(); i--; // 遇到非数字字符,需要回退一格,准备进入下一个for loop } else if (CharUtil.IsEnglishChar(c)) // 为啥这里不将空格并入英文字符里面呢?马萨卡... 用空格来分隔英文单词? { sb.Append(c); if (i == lastIdx) { list.Add(sb.ToString()); sb.Clear(); break; } c = sentence[++i]; while (CharUtil.IsEnglishChar(c)) { sb.Append(c); if (i == lastIdx) { list.Add(sb.ToString()); sb.Clear(); goto FINISH; } c = sentence[++i]; } list.Add(sb.ToString()); sb.Clear(); i--; // 遇到非英文字母,需要回退一格,进入下一个for loop } else { list.Add(c.ToString()); } } FINISH: return(list); }
/// <summary> /// 原子分词,连续的数字或者连续的英文空格作为一个整体词,其他单个字符自成一词 /// 第一列为词性,第二列为原子分词后的词 /// </summary> /// <param name="sentence"></param> /// <returns></returns> public static string[][] AtomSeg2Table(char[] sentence) { var table = new string[sentence.Length][]; // 是否可以table类型从交叉数组改为二维数组 for (int i = 0; i < sentence.Length; i++) { table[i] = new string[3]; //! 设置长度为 3,fst 为词性,snd为词本身,thd用于存储使用CRFModel Tag标注后的标签 } int size = 0; // 原子分词后的词数量,由于连续的数字被认为是一个整体,所以 size <= sentence.Length int lastIdx = sentence.Length - 1; // 最后的位置下标 var sb = new StringBuilder(); // 缓存连续的(阿拉伯)数字 for (int i = 0; i < sentence.Length; i++) { if (sentence[i] >= '0' && sentence[i] <= '9') { sb.Append(sentence[i]); if (i == lastIdx) // 如果当前已经是最后一个字符 { table[size][0] = "M"; //? 词性? table[size][1] = sb.ToString(); ++size; sb.Clear(); // 缓存结束 break; // 到达最后一个字符后退出for循环 } char c = sentence[++i]; // 到这里,说明当前字符是数字且尚未达到最后一个字符,则需要继续查看下一个字符是否是数字 while (c == '.' || c == '%' || (c >= '0' && c <= '9')) // 满足条件,表示连续的数值 { sb.Append(c); if (i == lastIdx) // 检测是否是最后一个字符 { table[size][0] = "M"; //? 词性? table[size][1] = sb.ToString(); ++size; sb.Clear(); // 缓存结束 goto FINISH; // 到达最后一个字符后退出for循环 } c = sentence[++i]; // 当前不是最后一个字符,则需要继续向后获取字符,以查看是否是数字 } // 当前字符 c 已经不是数字字符了,此时需要处理缓存的连续数字字符串 table[size][0] = "M"; table[size][1] = sb.ToString(); ++size; sb.Clear(); --i; // 当前字符c 不是数字字符,进入下一个for循环处理,于是,需要将 i 回退一格 } // 当前字符不是数字字符 else if (CharUtil.IsEnglishChar(sentence[i]) || sentence[i] == ' ') // 与数字字符处理类似,连续的英文or空格作为一个整体 { sb.Append(sentence[i]); if (i == lastIdx) { table[size][0] = "W"; table[size][1] = sb.ToString(); ++size; sb.Clear(); break; } char c = sentence[++i]; while (CharUtil.IsEnglishChar(c) || c == ' ') { sb.Append(sentence[i]); if (i == lastIdx) { table[size][0] = "W"; table[size][1] = sb.ToString(); ++size; sb.Clear(); goto FINISH; } c = sentence[++i]; } table[size][0] = "W"; table[size][1] = sb.ToString(); ++size; sb.Clear(); i--; } else { table[size][0] = table[size][1] = sentence[i].ToString(); size++; } } FINISH: if (size < sentence.Length) { return(ResizeArray(table, size)); } return(table); }