如何使用LINQ计算列表中的重复项


76

我有项目清单

  • 约翰·爱德
  • 马特ID
  • 约翰·爱德
  • 斯科特ID
  • 马特ID
  • 约翰·爱德
  • 卢卡斯ID

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

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

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

谢谢大家

编辑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 Hello World Times 234234
  • 2 Hello World。23432432

给你的结果很明显,计划将所有的项目,如不同的-正如我所说,你需要实现自定义比较,否则是无法选择不同的值
阿克苏

Answers:


106

您可以使用“分组依据” +“排序依据”。详细信息请参见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);
}

针对此帖子(现已删除):

如果您有一些自定义对象的列表,则需要使用自定义比较器或按特定属性分组。

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

根据您的最新更新:

您具有以下代码行:

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);
}

完成后,您现在可以快速浏览一下我正在查看的内容。
SpoiledTechie.com

选择新的{名称= g.Key,计数=计数,ID = g.First()。ID};这是使它起作用的那条线。谢谢阿久 它的.First.ID部分使其起作用。Ur Brilliant ...
SpoiledTechie.com,2009年

感谢您x.First().ID
所做

50

使用方法链的版本略短:

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);
}

简单的专业知识。
Hitsa

9

您也可以做字典:

 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);
        }

6

其他解决方案使用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;
}

0

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

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();
}        
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.