Lambda表达式找到差异

时间:2010-06-29 07:23:23

标签: c# lambda deferred-query

使用以下数据

string[] data = { "a", "a", "b" };

我非常想找到重复项并获得此结果:

a

我尝试了以下代码

var a = data.Distinct().ToList();
var b = a.Except(a).ToList();

显然这不起作用,我可以看到上面发生了什么,但我不知道如何解决它。

3 个答案:

答案 0 :(得分:11)

如果运行时没问题,可以使用

var duplicates = data.Where(s => data.Count(t => t == s) > 1).Distinct().ToList();

好老O(n ^ n)=)

编辑现在提供更好的解决方案。 =) 如果您定义了一个新的扩展方法,如

static class Extensions
{        

    public static IEnumerable<T> Duplicates<T>(this IEnumerable<T> input)
    {
        HashSet<T> hash = new HashSet<T>();
        foreach (T item in input)
        {
            if (!hash.Contains(item))
            {
                hash.Add(item);
            }
            else
            {
                yield return item;
            }
        }
    }
}

你可以使用

var duplicates = data.Duplicates().Distinct().ToArray();

答案 1 :(得分:5)

使用group by stuff,这些方法的表现相当不错。如果您正在使用大型数据集,那么唯一需要考虑的是内存开销很大。

from g in (from x in data group x by x)
where g.Count() > 1 
select g.Key;

- 或者如果您更喜欢扩展方法

data.GroupBy(x => x)
    .Where(x => x.Count() > 1)
    .Select(x => x.Key)

Count() == 1这是您的不同商品,Count() > 1哪个是一个或多个重复商品。

由于LINQ有点懒惰,如果你不想重新评估你的计算,你可以这样做:

var g = (from x in data group x by x).ToList(); // grouping result
// duplicates
from x in g
where x.Count() > 1 
select x.Key;
// distinct
from x in g
where x.Count() == 1 
select x.Key;

创建分组时,将创建一组集。假设它是一个插入O(1)的集合,则该方法的运行时间为O(n)。每项操作产生的成本有些高,但它应该等于接近线性的表现。

答案 2 :(得分:1)

对数据进行排序,遍历并记住最后一项。当前项目与最后一项相同时,它是重复的。这可以通过迭代或在O(n * log(n))时间内使用lambda表达式轻松实现。