如何使用 C# 检查文本文件中是否存在名词?

How to check if a noun exists in a text file with C#?

我试图在 C# 中找到一个库,它可以帮助我进行词性标记以从句子中识别名词,但无济于事。所以我决定根据我下载的文本文件中的名词列表检查我的字符串中的单词。我的代码假设句子中的第一个名词是动词所指的名词,我之所以这样假设是因为网站上留下的大多数评论并不由很多单词组成。所以这是我尝试将文本拆分为一个数组,然后循环遍历 noun.txt 文件中的每个名词,看看我的字符串是否存在。我的代码在下面,我只想 return The first noun foundNo noun detected 作为我方法的 return 类型。

string DetectNoun(string param){
  //split the input parameter into words based on spaces
  string[] words=param.ToLower().Split(" ");
  //read all the nouns in the text file into an array:NB all nouns are in lower case
  string[] allNouns=File.ReadAllLines("Nouns.txt");
  //loop through each noun in the array and check if any exists in our input parameter
  int j=0;
  for(int i=0;i>allNouns.Length;i++){
   if(allNouns[i]==words[j++]){
      //return this word as the noun found
       return allNouns[i];
     }
  }
  //if no match was found return no noun detected
  return "No noun detected";
}

使用示例输入 Samsung Television, No manual, Box included 测试了上面的内容。它保持 returning No noun was detected 尽管电视在我刚下载的 Nouns 的文本文件中。

您的原始代码有几个问题:

  1. 您按 space 拆分,因此在您的情况下,您得到(例如)television,,在您的单词列表中有一个逗号。比较时,您将 televisiontelevision, 进行比较,因此它不匹配。

  2. 您正在使用 == 进行比较,这在比较字符串时会“令人困惑”,您应该使用正确的字符串比较器。

  3. 你的 for 循环坏了,你只是在比较索引(第一个词和第一个名词,第二个词和第二个名词,等等)......另外,如果你名词列表比您的单词列表小,这将引发 IndexOutOfRange 异常

要解决所有这些问题:

  1. 在拆分之前从字符串中删除所有不需要的字符。我建议使用正则表达式(Regex.Replace(input, @"[^a-zA-Z\d ]", ""),但您需要检查它是否适合您的输入(特别是如果接收到非 a-Z 字母数字字符,如重音符号或变音符号等)

  2. 使用 StringComparer.OrdinalIgnoreCase 或 StringComparison.OrdinalIgnoreCase 而不是 ToLower()ToLower() 通常不是正确的做法,特别是在处理英语以外的文化时

  3. 我会使用 Linq 并从中创建一个 one-liner:

words.FirstOrDefault(x => allNouns.Contains(x, StringComparer.OrdinalIgnoreCase);

如果words中的no词包含在allNouns中,那就是returnnull,否则,第一个匹配。

综合起来:

string DetectNoun(string param){
  string[] words = Regex.Replace(param, @"[^a-zA-Z\d ]", "").Split(' ');
  // You should cache this somewhere if you plan to call this many times,
  // but I'll leave that up to you
  string[] allNouns=File.ReadAllLines("Nouns.txt");
  return words.FirstOrDefault(x => allNouns.Contains(x, StringComparer.OrdinalIgnoreCase)) 
            ?? "No noun detected";
}