在列表中计算出现次数的方法

66
有没有一种简单的方法在C#中计算列表中所有元素出现次数并将其保存在同一列表中?
类似这样的操作:
using System;
using System.IO;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using System.Linq;

string Occur;
List<string> Words = new List<string>();
List<string> Occurrences = new List<string>();

// ~170 elements added. . . 

for (int i = 0;i<Words.Count;i++){
    Words = Words.Distinct().ToList();
    for (int ii = 0;ii<Words.Count;ii++){Occur = new Regex(Words[ii]).Matches(Words[]).Count;}
         Occurrences.Add (Occur);
         Console.Write("{0} ({1}), ", Words[i], Occurrences[i]);
    }
}
8个回答

117

可以尝试这样做...

var l1 = new List<int>() { 1,2,3,4,5,2,2,2,4,4,4,1 };

var g = l1.GroupBy( i => i );

foreach( var grp in g )
{
  Console.WriteLine( "{0} {1}", grp.Key, grp.Count() );
}

根据评论编辑:我会尽力做到公正。

在我的示例中,这是一个 Func<int, TKey>,因为我的列表是整数。所以,我告诉 GroupBy 如何对我的项目进行分组。这个函数接受一个 int 值并返回我的分组的键。在这种情况下,我将得到一个 IGrouping<int,int>(由 int 键控制的 int 分组)。例如如果我改为 (i => i.ToString() ),那么我就是按字符串对我的分组进行分组。你可以想象一下比按“1”,“2”,“3”等分组更不寻常的示例,也许我可以编写一个返回“one”、“two”、“three”的函数来作为我的键……

private string SampleMethod( int i )
{
  // magically return "One" if i == 1, "Two" if i == 2, etc.
}

所以,这是一个接受整数并返回字符串的函数,就像...

i =>  // magically return "One" if i == 1, "Two" if i == 2, etc. 

然而,因为原问题要求知道原始列表值及其计数,所以我只是使用了一个整数来作为我的整数分组的键,使我的示例更简单。


1
+1. 这种方法非常优雅,可以计算每个不同元素的出现次数。 - Stan R.
1
FindAll 返回原始列表中与谓词匹配的元素列表,因此您需要为每个唯一元素执行一次以查找该元素的计数。 - JP Alioto
1
只需使用它,绝佳的解决方案。如果您想对其进行排序,请使用以下代码:var g = l1.GroupBy( i => i ).OrderByDescending(group => group.Count()); - aloisdg

25
你可以像这样从一个事物列表中进行计数。
IList<String> names = new List<string>() { "ToString", "Format" };
IEnumerable<String> methodNames = typeof(String).GetMethods().Select(x => x.Name);

int count = methodNames.Where(x => names.Contains(x)).Count();

计算单个元素

string occur = "Test1";
IList<String> words = new List<string>() {"Test1","Test2","Test3","Test1"};

int count = words.Where(x => x.Equals(occur)).Count();

1
+1:我花了一些时间才明白GetMethods()只是你的事物列表。 :) - Robert Harvey
是的,我考虑到了这一点,并决定让它更易读。谢谢,尽管我误读了问题。它说要计算“所有元素”...哎呀。不过这仍然足够有用。 - Stan R.
@StanR. - 这个解决方案对我的问题有效。但是,列表中是否有一种方法可以计算大于或等于某个单词的出现次数?我正在使用“int”类型而不是“string”。 - Mihir Patel
@MihirPatel 只需将 .Where 更改为 x > num || x == num - Stan R.

15
var wordCount =
    from word in words
    group word by word into g
    select new { g.Key, Count = g.Count() };    

这段内容来自linqpad的示例之一。


3
public void printsOccurences(List<String> words)
{
    var selectQuery =
        from word in words
        group word by word into g
        select new {Word = g.Key, Count = g.Count()};
    foreach(var word in selectQuery)
        Console.WriteLine($"{word.Word}: {word.Count}");*emphasized text*
}

1

这是一个避免使用Linq但只使用略微更多代码的版本。

// using System.Collections.Generic;

Dictionary<int, int> oGroups = new Dictionary<int, int>();
List<int> oList = new List<int>() { 1, 2, 3, 4, 5, 2, 2, 2, 4, 4, 4, 1 };

foreach (int iCurrentValue in oList)
{
    if (oGroups.ContainsKey(iCurrentValue))
        oGroups[iCurrentValue]++;
    else
        oGroups.Add(iCurrentValue, 1);
}

foreach (KeyValuePair<int, int> oGroup in oGroups)
{
    Console.WriteLine($"Value {oGroup.Key} appears {oGroup.Value} times.");
}

0
该代码返回一个包含单词及其出现次数的字典:
            var wordsDic = Words
            .GroupBy(p => p)
            .ToDictionary(p => p.Key, q => q.Count());

0
        List<int> list = new List<int>()
        { 1,2,3,4,5,2,2,2,1           
        };

        //int a=0

        var a = list.GroupBy(x => x) ;

        foreach (var y in a)
        {
            Console.WriteLine("The element" + y.Key);
            Console.WriteLine(y.Count());
        }

感谢您对Stack Overflow社区做出贡献的兴趣。这个问题已经有很多答案了,其中包括一个经过社区广泛验证的答案。您确定您的方法之前没有被提到过吗?如果是这样的话,能否解释一下您的方法有何不同,什么情况下您的方法可能更好,并且/或者为什么您认为之前的答案不够满意。您能否友好地编辑您的答案并提供解释? - undefined

-4

你的外层循环正在遍历列表中的所有单词。这是不必要的,会导致问题。移除它,代码就应该正常工作了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接