【问题标题】:How to Count Duplicates in List with LINQ如何使用 LINQ 计算列表中的重复项
【发布时间】:2009-01-18 03:41:23
【问题描述】:

我有一个物品清单

  • 约翰 ID
  • 马特 ID
  • 约翰 ID
  • 斯科特 ID
  • 马特 ID
  • 约翰 ID
  • 卢卡斯 ID

我想将它们推回到这样的列表中,这也意味着我想按最多的重复项进行排序。

  • 约翰 ID 3
  • 马特 ID 2
  • 斯科特 ID 1
  • 卢卡斯 ID 1

让我知道如何使用 LINQ 和 C# 做到这一点。

谢谢大家

EDIT 2 显示代码:

    List<game> inventory = new List<game>();
    drinkingforDataContext db = new drinkingforDataContext();
    foreach (string item in tbTitle.Text.Split(' '))
    {

        List<game> getItems = (from dfg in db.drinkingfor_Games
                               where dfg.game_Name.Contains(tbTitle.Text)
                               select new game
                               {
                                   gameName = dfg.game_Name,
                                   gameID = Boomers.Utilities.Guids.Encoder.EncodeURLs(dfg.uid)
                               }).ToList<game>();

        for (int i = 0; i < getItems.Count(); i++)
        {
            inventory.Add(getItems[i]);
        }
    }

    var items = (from xx in inventory
                 group xx by xx into g
                 let count = g.Count()
                 orderby count descending
                 select new
                    {
                        Count = count,
                        gameName = g.Key.gameName,
                        gameID = g.Key.gameID
                    });

    lvRelatedGames.DataSource = items;
    lvRelatedGames.DataBind();

此查询显示以下结果:

  • 1 你好世界时报
  • 1 你好世界时报
  • 1 Hello World。
  • 1 你好世界时报
  • 1 你好世界时报
  • 1 你好世界时报
  • 1 Hello World。
  • 1 你好世界时报

它给了我计数和名称,但它没有给我游戏的 ID....

它应该显示:

  • 6 你好世界时报 234234
  • 2 你好世界。 23432432

【问题讨论】:

  • 鉴于您的结果,很明显程序会将您的所有项目视为不同的 - 正如我所说,您需要实现自定义比较器,否则无法选择不同的值

标签: c# linq


【解决方案1】:

您可以使用“分组依据”+“排序依据”。详情见LINQ 101

var list = new List<string> {"a", "b", "a", "c", "a", "b"};
var q = from x in list
        group x by x into g
        let count = g.Count()
        orderby count descending
        select new {Value = g.Key, Count = count};
foreach (var x in q)
{
    Console.WriteLine("Value: " + x.Value + " Count: " + x.Count);
}

回复this post(现已删除):

如果您有一些自定义对象的列表,那么您需要使用 custom comparer 或按特定属性分组。

同样查询无法显示结果。向我们展示完整的代码以获得更好的帮助。

根据您的最新更新:

你有这行代码:

group xx by xx into g

由于 xx 是一个自定义对象系统不知道如何将一个项目与另一个项目进行比较。 正如我已经写过的,您需要指导编译器并提供一些将在对象比较中使用的属性或提供自定义比较器。这是一个例子:

请注意,我使用 Foo.Name 作为键 - 即对象将根据 Name 属性的值进行分组。

有一个问题 - 您根据名称将 2 个对象视为重复对象,但是 Id 呢?在我的示例中,我只取组中第一个对象的 ID。如果您的对象具有不同的 ID,则可能会出现问题。

//Using extension methods
var q = list.GroupBy(x => x.Name)
            .Select(x => new {Count = x.Count(), 
                              Name = x.Key, 
                              ID = x.First().ID})
            .OrderByDescending(x => x.Count);

//Using LINQ
var q = from x in list
        group x by x.Name into g
        let count = g.Count()
        orderby count descending
        select new {Name = g.Key, Count = count, ID = g.First().ID};

foreach (var x in q)
{
    Console.WriteLine("Count: " + x.Count + " Name: " + x.Name + " ID: " + x.ID);
}

【讨论】:

  • 完成,您现在可以大致了解我在看什么了。
  • 选择新的 {Name = g.Key, Count = count, ID = g.First().ID};这是使它起作用的线。谢谢阿库。它是使它工作的 .First.ID 部分。你的辉煌...
  • 感谢x.First().ID 的事情
【解决方案2】:

使用方法链的略短版本:

var list = new List<string> {"a", "b", "a", "c", "a", "b"};
var q = list.GroupBy(x => x)
            .Select(g => new {Value = g.Key, Count = g.Count()})
            .OrderByDescending(x=>x.Count);

foreach (var x in q)
{
    Console.WriteLine("Value: " + x.Value + " Count: " + x.Count);
}

【讨论】:

  • 简单而专业。
【解决方案3】:

你也可以做字典:

 var list = new List<string> { "a", "b", "a", "c", "a", "b" };
 var result = list.GroupBy(x => x)
            .ToDictionary(y=>y.Key, y=>y.Count())
            .OrderByDescending(z => z.Value);

 foreach (var x in result)
        {
            Console.WriteLine("Value: " + x.Key + " Count: " + x.Value);
        }

【讨论】:

    【解决方案4】:

    其他解决方案使用GroupByGroupBy 很慢(它包含内存中的所有元素)所以我编写了自己的方法CountBy

    public static Dictionary<TKey,int> CountBy<TSource,TKey>(this IEnumerable<TSource> source, Func<TSource,TKey> keySelector)
    {
        var countsByKey = new Dictionary<TKey,int>();
        foreach(var x in source)
        {
            var key = keySelector(x);
            if (!countsByKey.ContainsKey(key))
                countsByKey[key] = 0;
            countsByKey[key] += 1;
        }
        return countsByKey;
    }
    

    【讨论】:

      【解决方案5】:

      为什么不发布新答案!如今,我认为您可以做类似...
      var duplicatesCount = listVariable.Count(o =&gt; o.Equals(listElement));
      然后只需在新列表中添加带有重复计数的每个元素,使用 !listVariable.Contains(elem) 重复阻止程序

      【讨论】:

      • 发布最新信息的好主意。然而“我认为”?你不应该在发帖前确定吗?
      【解决方案6】:

      这是完整的程序,请查看此

      static void Main(string[] args)
      {
          List<string> li = new List<string>();
          li.Add("Ram");
          li.Add("shyam");
          li.Add("Ram");
          li.Add("Kumar");
          li.Add("Kumar");
      
          var x = from obj in li group obj by obj into g select new { Name = g.Key, Duplicatecount = g.Count() };
          foreach(var m in x)
          {
              Console.WriteLine(m.Name + "--" + m.Duplicatecount);
          }
          Console.ReadLine();
      }        
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-01-13
        • 1970-01-01
        • 2019-08-17
        • 1970-01-01
        • 2011-03-30
        • 1970-01-01
        • 2019-02-04
        • 1970-01-01
        相关资源
        最近更新 更多