LINQy way to check if any objects in a collection have the same property value

后端 未结 6 572
庸人自扰
庸人自扰 2020-12-17 00:07

I have a class Agent with a property Id

Given a collection of Agents I need to check if any of them have duplicate Ids.

I am currently doing this with a hash

相关标签:
6条回答
  • 2020-12-17 00:23

    For what it's worth, I just compared the two methods we've struck upon in this thread. First I defined a helper class:

    public class Foo
    {
        public int ID;
    }
    

    ... and then made a big list of instances with a random ID:

    var list = new List<Foo>();
    
    var r = new Random();
    
    for (int i = 0; i < 10000; i++) list.Add(new Foo { ID = r.Next() });
    

    ... and lastly, timed the code:

    var sw = new Stopwatch();
    sw.Start();
    bool b = list.Any(i => list.Where(j => i != j).Any(j => j.ID == i.ID));
    Console.WriteLine(b);
    Console.WriteLine(sw.ElapsedTicks);
    
    sw.Reset();
    sw.Start();
    b = (list.GroupBy(i => i.ID).Count() != list.Count);
    Console.WriteLine(b);
    Console.WriteLine(sw.ElapsedTicks);
    

    Here's one output:

    False

    59392129

    False

    168151

    So I think it's safe to say that grouping and then comparing the count of groups to the count of items is way, way faster than doing a brute-force "nested Any" comparison.

    0 讨论(0)
  • 2020-12-17 00:25

    Similar to Y Low's approach,

    Edited:

     var duplicates = agents.GroupBy(a => a.ID).Where(a=>a.Count() > 1);
    
     foreach (var agent in duplicates)
     {
             Console.WriteLine(agent.Key.ToString());
     }
    
    0 讨论(0)
  • 2020-12-17 00:27
    foreach(var agent in Agents) {
        if(Agents.Count(a => a.ID == agent.ID) > 1)
            Console.WriteLine("Found: {0}", agent.ID);
    }
    
    0 讨论(0)
  • 2020-12-17 00:42

    this is how i would do it without the need to do group-by in one line:

     List<Agent> duplicates = new HashSet<Agent>(agents.Where(c => agents.Count(x => x.ID == c.ID) > 1)).ToList();
    
    0 讨论(0)
  • 2020-12-17 00:43

    My take (no counting!):

    var duplicates = agents
      .GroupBy(a => a.ID)
      .Where(g => g.Skip(1).Any());
    
    0 讨论(0)
  • 2020-12-17 00:49
    bool b = list.Any(i => list.Any(j => j.ID == i.ID && j != i));
    

    That's a bit of a brute-force approach but it works. There might be a smarter way to do it using the Except() extension method.

    Edit: You didn't actually say that you needed to know which items are "duplicated", only that you needed to know whether any where. This'll do the same thing except give you a list you can iterate over:

    list.Where(i => list.Any(j => j.ID == i.ID && j != i))

    I like the grouping approach too (group by ID and find the groups with count > 1).

    0 讨论(0)
提交回复
热议问题