简体   繁体   English

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

[英]How to Count Duplicates in List with LINQ

I have a list of items我有一个项目清单

  • John ID约翰身份证
  • Matt ID马特身份证
  • John ID约翰身份证
  • Scott ID斯科特身份证
  • Matt ID马特身份证
  • John ID约翰身份证
  • Lucas ID卢卡斯身份证

I want to shove them back into a list like so which also means I want to sort by the highest number of duplicates.我想将它们推回到这样的列表中,这也意味着我想按重复项的最高数量进行排序。

  • John ID 3约翰 ID 3
  • Matt ID 2马特 ID 2
  • Scott ID 1斯科特 ID 1
  • Lucas ID 1卢卡斯 ID 1

Let me know how I can do this with LINQ and C#.请告诉我如何使用 LINQ 和 C# 执行此操作。

Thanks All谢谢大家

EDIT 2 Showing Code:编辑 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();

This query displays these results:此查询显示以下结果:

  • 1 hello world times 1 你好世界时报
  • 1 hello world times 1 你好世界时报
  • 1 Hello World. 1 你好世界。
  • 1 hello world times 1 你好世界时报
  • 1 hello world times 1 你好世界时报
  • 1 hello world times 1 你好世界时报
  • 1 Hello World. 1 你好世界。
  • 1 hello world times 1 你好世界时报

It gives me the count and name, but it doesn't give me the ID of the game....它给了我数量和名称,但没有给我游戏的 ID……

It should display:它应该显示:

  • 6 hello world times 234234 6 你好世界时报 234234
  • 2 Hello World. 2 你好世界。 23432432 23432432

You can use "group by" + "orderby".您可以使用“group by”+“orderby”。 See LINQ 101 for details有关详细信息,请参阅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);
}

In response to this post (now deleted):回复这篇文章(现已删除):

If you have a list of some custom objects then you need to use custom comparer or group by specific property.如果您有一些自定义对象的列表,那么您需要使用 自定义比较器或按特定属性分组。

Also query can't display result.查询也无法显示结果。 Show us complete code to get a better help.向我们展示完整的代码以获得更好的帮助。

Based on your latest update:根据您的最新更新:

You have this line of code:你有这行代码:

group xx by xx into g

Since xx is a custom object system doesn't know how to compare one item against another.由于 xx 是一个自定义对象系统不知道如何将一个项目与另一个项目进行比较。 As I already wrote, you need to guide compiler and provide some property that will be used in objects comparison or provide custom comparer.正如我已经写过的,您需要引导编译器并提供一些将用于对象比较的属性或提供自定义比较器。 Here is an example:下面是一个例子:

Note that I use Foo.Name as a key - ie objects will be grouped based on value of Name property.请注意,我使用Foo.Name作为键 - 即对象将根据Name属性的值进行分组。

There is one catch - you treat 2 objects to be duplicate based on their names, but what about Id ?有一个问题 - 您根据名称将 2 个对象视为重复对象,但是 Id 呢? In my example I just take Id of the first object in a group.在我的示例中,我只获取组中第一个对象的 ID。 If your objects have different Ids it can be a problem.如果您的对象具有不同的 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);
}

Slightly shorter version using methods chain:使用方法链的略短版本:

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

You can also do Dictionary:你也可以做字典:

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

The other solutions use GroupBy .其他解决方案使用GroupBy GroupBy is slow (it holds all the elements in memory) so I wrote my own method CountBy : GroupBy很慢(它将所有元素保存在内存中)所以我编写了自己的方法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;
}

Here is the complete programme please check this这是完整的程序,请检查这个

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

Why not to post an new answer!为什么不发布一个新的答案! Nowadays, i think you can do just something like...如今,我认为你可以做一些像......
var duplicatesCount = listVariable.Count(o => o.Equals(listElement));
then just add each element with duplicateCount at new list, with !listVariable.Contains(elem) duplicate blocker然后只需在新列表中添加带有重复!listVariable.Contains(elem)每个元素,并使用!listVariable.Contains(elem)重复阻止程序

another solution另一种解决方案

public static void Main()
{
        var list = new List<string> {"a", "b", "a", "c", "a", "b"};
        list.GroupBy(x => x)
            .Select(x => new { Value = x.Key, Count = x.Count()} )
            .Where(x => x.Count > 1).ToList()
            .ForEach(x => Console.WriteLine($"Value: {x.Value} Count: {x.Count}"));
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM