【问题标题】:LINQy way to check if any objects in a collection have the same property valueLINQy 方法来检查集合中的任何对象是否具有相同的属性值
【发布时间】:2008-11-23 02:20:38
【问题描述】:

我有一个具有属性 ID 的类代理

给定一组代理,我需要检查其中是否有重复的 ID。

我目前正在使用哈希表执行此操作,但我正在尝试获取 Linq-ified,这样做的好方法是什么?

【问题讨论】:

    标签: c# linq


    【解决方案1】:

    类似于 Y Low 的方法,

    已编辑:

     var duplicates = agents.GroupBy(a => a.ID).Where(a=>a.Count() > 1);
    
     foreach (var agent in duplicates)
     {
             Console.WriteLine(agent.Key.ToString());
     }
    

    【讨论】:

    • 嗯,GroupBy,很有趣。那么这不可行吗: bool b = (agents.GroupBy(a=>a.Id)).Count() == agents.Count();
    • 刚发了一个更新,把两者(GroupBy和Where)结合起来就可以得到重复对象的key了……
    • Ha - 将组数与元素数进行比较。这是一个有灵感的想法。
    • 我想知道分组是否会比 Any() 方法效率低一点,因为 Any() 一旦找到匹配项就会放弃,而分组必须访问每个元素.
    • Matt...我猜我们必须测试一下。我只是像处理 SQL 问题一样处理它。我是一个 db 人,所以我喜欢 Linq,因为它使用类似 Sql 的方法来解决此类问题......
    【解决方案2】:

    对于它的价值,我只是比较了我们在这个线程中遇到的两种方法。首先我定义了一个辅助类:

    public class Foo
    {
        public int ID;
    }
    

    ...然后用随机 ID 制作了一个大的实例列表:

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

    ...最后,给代码计时:

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

    这是一个输出:

    错误

    59392129

    错误

    168151

    所以我认为可以肯定地说,分组然后将组数与项目数进行比较比进行暴力“嵌套 Any”比较快方式。 p>

    【讨论】:

      【解决方案3】:

      我的看法(不算数!):

      var duplicates = agents
        .GroupBy(a => a.ID)
        .Where(g => g.Skip(1).Any());
      

      【讨论】:

      • 此语句返回重复项,而不是是否有重复项。一旦发现任何重复项,我就可以停止=您的声明后跟 Any();将此方法与 Distinct/Count 方法进行比较。 used sequence = new int[]{1}.Concat(Enumerable(0, 10000000); 唉 groupby 方法慢了 6 倍。这可能是因为 GroupBy 已完全执行,即使已经找到重复项?跨度>
      • @HaraldDutch 正确。尽管 GroupBy 是惰性的,但它在评估时会被完全评估。
      【解决方案4】:
      foreach(var agent in Agents) {
          if(Agents.Count(a => a.ID == agent.ID) > 1)
              Console.WriteLine("Found: {0}", agent.ID);
      }
      

      【讨论】:

        【解决方案5】:
        bool b = list.Any(i => list.Any(j => j.ID == i.ID && j != i));
        

        这是一种蛮力的方法,但它确实有效。使用 except() 扩展方法可能有更聪明的方法。

        编辑:你实际上并没有说你需要知道哪些项是“重复的”,只是你需要知道是否在哪里。除了给你一个可以迭代的列表之外,这将做同样的事情:

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

        我也喜欢分组方法(按 ID 分组并找到计数 > 1 的组)。

        【讨论】:

          【解决方案6】:

          这就是我不需要在一行中进行分组的方式:

           List<Agent> duplicates = new HashSet<Agent>(agents.Where(c => agents.Count(x => x.ID == c.ID) > 1)).ToList();
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2023-01-07
            • 2023-03-26
            • 2017-10-23
            • 2020-12-27
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多