2010-06-29 82 views
5

用下面的數據Lambda表達式找到差異

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

我會非常想找到重複的和得到這樣的結果:

a 

我嘗試下面的代碼

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

顯然這不起作用,我可以看到上面發生了什麼,但我不知道如何解決它。

回答

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

散列集合的好解決方案。我一直在思考這些問題,但顯然還沒有醒來...... – Noldorin 2010-06-29 07:37:51

+0

真的很好的解決方案!我知道我可以這樣做,但不知道有可能擴展這樣的語言! – user375049 2010-06-29 07:43:35

1

排序數據,遍歷數據並記住最後一項。當前項目與最後一項相同時,其重複。這可以通過迭代或在O(n * log(n))時間內使用lambda表達式輕鬆實現。

+0

這就是我想要做的,但是學習如何編寫lambda表達式並且不知道如何去做。 – user375049 2010-06-29 07:41:30

5

的東西使用組,這些方法的表現都相當不錯。如果您正在處理大型數據集,那麼只關心大量內存開銷。

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

--OR,如果你喜歡的擴展方法

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)。每項業務的發生成本都較高,但應該接近線性業績。

+0

我給你投票,但需要15代表爲了做到這一點(!)好例子:) – user375049 2010-06-29 07:44:59

+0

如果你想改變你最喜歡的答案。 – 2010-06-29 07:46:57