LINQ检查集合中任何对象是否具有相同属性值的方法

7

我有一个名为Agent的类,其中有一个属性Id。

给定一组代理,我需要检查是否有任何代理具有重复的Id。

我目前使用哈希表来实现这个功能,但是我正在尝试使用Linq,有没有好的方法可以做到这一点?

6个回答

13

类似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(); - George Mauer
刚刚发布了一个更新,只需将 GroupBy 和 Where 两个方法组合起来即可获取重复对象的键... - Codewerks
哈 - 将组数与元素数量进行比较。那是一个灵感十足的想法。 - Matt Hamilton
我在想,相比于 Any() 方法,使用分组是否会稍微低效一些,因为 Any() 一旦找到匹配项就停止搜索,而分组需要访问每个元素。 - Matt Hamilton
很高兴你喜欢它Matt。你可能对效率是正确的,但我发现这更易读。 - George Mauer
显示剩余3条评论

4

就我所知,我刚刚比较了这个线程中提到的两种方法。首先,我定义了一个帮助类:

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

因此,我认为将组合后的组数与项目数进行比较要比进行暴力“嵌套任意”比较快得多。


2

我的看法(不包括计数!):

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

这个语句返回重复项,而不是是否存在重复项。只要发现任何一个重复项,我就可以停止 = 您的语句后跟 Any(); 将此方法与 Distinct/Count 方法进行比较。使用 sequence = new int[]{1}.Concat(Enumerable(0, 10000000);。遗憾的是,GroupBy 方法要慢6倍。这可能是因为即使已经找到重复项,仍然完全执行了 GroupBy 吗? - Harald Coppoolse
@HaraldDutch 正确。尽管 GroupBy 是惰性的,但在评估时它会被完全评估。 - Amy B

1
foreach(var agent in Agents) {
    if(Agents.Count(a => a.ID == agent.ID) > 1)
        Console.WriteLine("Found: {0}", agent.ID);
}

1
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 的组)。


0

这是我在不需要进行分组的情况下如何完成它的方法:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接