如何使用Linq删除所有唯一对象

时间:2015-12-16 22:25:19

标签: c# .net linq unique

说,我有LinkedList<T1>这样:

{ A, B, C, D, E, F, G, H, I, J }

在此列表中:

B.param == C.param == F.param == p1G.param == I.param == p2,所以我必须接下来:

{ B, C, F, G, I }

2 个答案:

答案 0 :(得分:4)

以下是如何做到这一点:

list = new LinkedList<T1>(
    list
    .GroupBy(x => x.param)
    .Where(x => x.Count() > 1)
    .SelectMany(x => x));

您可以按param属性对项目进行分组(这就像创建组列表一样,每个组包含共享param属性相同值的项目。)

在您的示例中,这将创建7个组:

{A},{B,C,F},{D},{E},{G,I},{H},{J}

然后,您只通过仅包含具有多个项目的组来过滤组(从而删除具有单个项目的组)。

当您保留包含多个项目的群组时,您会保留{B,C,F}和{G,I}。

然后,您通过SelectMany将这些群体展平为单个项目,这会为您提供{B,C,F,G,I}。

效果测试:

如果您的列表很大,那么您应该考虑性能。我提供的解决方案非常有效,以下是测试它并将性能与其他解决方案进行比较的方法:

List<T1> list = new List<T1>();

Random rnd = new Random();

for (int i = 0; i < 10000; i++)
{
    list.Add(new T1 { param = rnd.Next(1,5000).ToString()});
}

Stopwatch sw = Stopwatch.StartNew();

var result1 =
    list
        .GroupBy(x => x.param)
        .Where(x => x.Count() > 1)
        .SelectMany(x => x)
        .ToList();

long result1_time = sw.ElapsedMilliseconds;

sw.Restart();

var result2 = list.Where(el => list.Any(z => z.param == el.param && z != el)).ToList();

long result2_time = sw.ElapsedMilliseconds;

Console.WriteLine(result1_time);
Console.WriteLine(result2_time);

Console.ReadLine();

在我的机器上,我的解决方案需要大约3毫秒,另一个解决方案需要大约2500毫秒。

答案 1 :(得分:3)

这应该有效

var b = list.Where(el => list.Any(z => z.param == el.param && z != el));