C#列表中重复项的计数

3

我想知道如何在C#的winform应用程序中计算列表中所有重复字符串的数量。

List<string> colorList = new List<string> { "red", "red", "yellow", "blue", "blue", "orange", "green", "red" };

例如,我有上面的列表,计数将为5,因为“red”出现了3次,“blue”出现了两次。
愿意使用循环或LINQ或任何必要的东西。
在我的实际程序中,这个列表可以相当大,有成千上万个条目,因此性能也是需要考虑的因素。
谢谢!

注意:我不需要知道哪个值出现最多或其他任何信息,严格来说,只要在找到重复值时递增计数即可。 - Matthew Keron
请注意最好编辑您的问题而不是将其发布为评论。 - Klaus Gütter
5个回答

15

如果您只需要总数:

var total = colorList.GroupBy(_ => _).Where(_ => _.Count() > 1).Sum(_ => _.Count());

一种在处理大数据集时可能更快的替代方法:

var hashset = new HashSet<string>(); // to determine if we already have seen this color
var duplicates = new HashSet<string>(); // will contain the colors that are duplicates
var count = 0;
foreach (var color in colorList)
{
    if (!hashset.Add(color))
    {
        count++;
        if (duplicates.Add(color))
            count++;
    }
}

更新:使用由约2^25(约3000万)个条目组成的列表对两种方法进行了测量:第一种方法需要3.7秒,第二种方法需要3.2秒。


喜欢你使用丢弃的方式。 - Anu Viswan
非常感谢!感谢您的建议,这个完美地解决了问题。 - Matthew Keron

7
如果您仅需要重复项的计数:
 List<string> colorList = new List<string> { "red", "red", "yellow", "blue", "blue", "orange", "green", "red" };

 var count = colorList.GroupBy(item => item)
                      .Where(item => item.Count() > 1)
                      .Sum(item => item.Count());

尝试使用此方法获取逐个项目的详细信息:

var result = colorList.GroupBy(item => item)
                      .Select(item => new
                          {
                              Name = item.Key,
                              Count = item.Count()
                          })
                      .OrderByDescending(item => item.Count)
                      .ThenBy(item => item.Name)
                      .ToList();

1

在C#中计算重复项的另一种方法可以如下所示:

 var duplicates = from d in list
 group d by d into c
 let count = c.Count()
 orderby count descending
 select new { Value = c.Key, Count = count };

  foreach (var v in duplicates)
  {
     string strValue = v.Value;
     int Count = v.Count;
  }

0

虽然不如被接受的答案快,但是作为参考,我们也可以使用字典来计算命中次数:

var map = new Dictionary<string, int>();
foreach (var color in colorList))
{
    if (map.ContainsKey(color)) map[color]++;
    else map.Add(color, 1);
}

return map.Values.Count(x => x > 1);

它比 LINQ 的 GroupBy 快得多


0

我会不用 group by 来完成它。

List<string> colorList = new List<string> { "red", "red", "yellow", "blue", "blue", "orange", "green", "red" };
        var count = 0;
        foreach (var item in colorList.Distinct().ToList())
        {
            var cnt = colorList.Count(i => i.Equals(item, StringComparison.InvariantCultureIgnoreCase));
            if (cnt > 1)
                count += cnt;

        }

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