首页 > 解决方案 > Lambda 函数在列表 C# 中查找最流行的单词

问题描述

我目前有一个我认为是 C# 的 lambda 函数(对编码来说还很新,之前没有使用过 lambda 函数,所以很容易),它在列表中添加重复的字符串(来自 FilteredList)并计算出现次数和存储计数值。我只想要列表中最常用的单词,我已经通过“groups.OrderBy()...etc) 行设法做到了,但是我很确定我已经让这对自己来说非常复杂并且非常效率低下。以及通过添加字典和键值对。

   
            var groups =
        from s in FilteredList
        group s by s into g
        // orderby g descending
        select new
        {
            Stuff = g.Key,
            Count = g.Count()

        };
 groups = groups.OrderBy(g => g.Count).Reverse().Take(1);

var dictionary = groups.ToDictionary(g => g.Stuff, g => g.Count);

foreach (KeyValuePair<string, int> kvp in dictionary)
            {   
                Console.WriteLine("Key = {0}, Value = {1}", kvp.Key, kvp.Value);
                
            }
            

有人可以帮我解决这个问题并解释一下,或者至少为我指明一些学习材料的方向,这可能有助于我更好地理解这一点。

更多信息:FilteredList 来自一大段外部文本,读入字符串列表(由分隔符分割),减去字符串停用词列表。

另外,如果这不是 lambda 函数,或者我在这里的任何信息不正确,请纠正我,以便我可以解决问题以使其更相关并帮助我找到答案。

提前致谢。

标签: c#lambda

解决方案


是的,我认为您有些过于复杂了。假设您的单词列表如下:

var words = new[] { "what's", "the", "most", "most", "most", "mentioned", "word", "word" };

您可以通过以下方式获得最常提及的词:

words.GroupBy(w => w).OrderByDescending(g => g.Count()).First().Key;

当然,您可能希望将其分配给一个变量,并且在外观上您可能希望将其分成多行:

var mostFrequentWord = words
  .GroupBy(w => w)                       //make a list of sublists of words, like a dictionary of word:list<word>
  .OrderByDescending(g => g.Count())     //order by sublist count descending
  .First()                               //take the first list:sublist
  .Key;                                  //take the word 

GroupBy 产生一个 IGrouping 的集合,就像一个Dictionary<string, List<string>>. 它将每个单词(字典的键)映射到该单词所有出现的列表。在我的示例数据中,“most”的 IGroupingKey将映射到List<string>其中{"most","most","most"}元素数量最多为 3 的 a。如果我们OrderByDescending基于Count()每个列表的 进行分组,然后取First,我们将得到使用“most”键,所以我们需要做的就是IGrouping检索实际单词Key

如果单词只是较大对象的属性之一,那么您可以.GroupBy(o => o.Word). 如果您想要 IGrouping 中的其他一些属性,例如它的第一个或最后一个,那么您可以使用它而不是 Key,但请记住,您最终使用的属性可能每次都不同,除非您强制在分组


如果你想让这比安装 MoreLinq 和使用 MaxBy 更有效;获得 Max word 通过列表计数意味着您可以避免排序操作。您也可以避免使用 LINQ 并使用字典:

string[] words = new[] { "what", "is", "the", "most", "most", "most", "mentioned", "word", "word" };

var maxK = "";
var maxV = -1;
var d = new Dictionary<string, int>();
foreach(var w in words){
  if(!d.ContainsKey(w))
    d[w] = 0;
  d[w]++;
  if(d[w] > maxV){
    maxK = w; 
    maxV = d[w];
  }
}
Console.WriteLine(maxK);

这保留了一个字典,它可以随时计算单词,并且比 LINQ 路由更有效,因为它只需要单词列表的单次传递,加上相关的字典查找,而不是“将单词列表转换为子列表列表,排序列表”按子列表计数的子列表,取第一个列表项"


推荐阅读