Lambda表达式用于查找差异

5

使用以下数据

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

我非常希望能找到重复项并得到以下结果:
a

我尝试了以下代码。
var a = data.Distinct().ToList();
var b = a.Except(a).ToList();

显然这种方法行不通,我能看到上面发生了什么,但我不确定如何解决它。
3个回答

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

使用哈希集合的好解决方案。我也在考虑这个方向,但显然还没有完全清醒... - Noldorin
确实使用哈希集合是一个好的解决方案!我知道我可以这样做,但不知道可以像那样扩展语言! - user375049

5

使用group by来处理数据,这些方法的性能相当不错。唯一需要考虑的是如果你正在处理大数据集,可能会有很大的内存开销。

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)。每个操作的成本相对较高,但应该等同于近似线性的性能。

我想给你投赞成票,但需要15个声望才能这样做!很好的例子 :) - user375049
如果您想更改首选答案,可以这样做。 - John Leidegren

1

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


这就是我想做的事情,但学习如何写lambda表达式并不明显该怎么做。 - user375049

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