2013-04-24 80 views
18

我正在尋找一種非常快速的方法來檢查對象列表中的重複項。檢查對象列表中的重複項#

我想簡單地通過列表循環和做手工比較這種方式,但我認爲LINQ可能會提供一個更好的解決方案...

假設我有一個對象...

public class dupeCheckee 
{ 
    public string checkThis { get; set; } 
    public string checkThat { get; set; } 

    dupeCheckee(string val, string val2) 
    { 
     checkThis = val; 
     checkThat = val2; 
    } 
} 

而且我的那些對象

List<dupeCheckee> dupList = new List<dupeCheckee>(); 
dupList.Add(new dupeCheckee("test1", "value1")); 
dupList.Add(new dupeCheckee("test2", "value1")); 
dupList.Add(new dupeCheckee("test3", "value1")); 
dupList.Add(new dupeCheckee("test1", "value1"));//dupe 
dupList.Add(new dupeCheckee("test2", "value1"));//dupe... 
dupList.Add(new dupeCheckee("test4", "value1")); 
dupList.Add(new dupeCheckee("test5", "value1")); 
dupList.Add(new dupeCheckee("test1", "value2"));//not dupe 

我需要找到該列表中的受騙者名單。當我找到它時,我需要做一些額外的邏輯 不一定刪除它們。

當我使用LINQ一些我的GroupBy如何拋出異常......

'System.Collections.Generic.List<dupeCheckee>' does not contain a definition for 'GroupBy' and no extension method 'GroupBy' accepting a first argument of type 'System.Collections.Generic.List<dupeCheckee>' could be found (are you missing a using directive or an assembly reference?) 

這是告訴我,我缺少的庫。我很難搞清楚哪一個。

一旦我弄清楚,但我怎麼會基本上檢查這兩個條件... IE checkThis和checkThat都出現不止一次?

更新:我想出了

這是我想出了做快速研究後LINQ查詢...

test.Count != test.Select(c => new { c.checkThat, c.checkThis }).Distinct().Count() 

我不能肯定這是否是肯定更好比這個答案...

var duplicates = test.GroupBy(x => new {x.checkThis, x.checkThat}) 
        .Where(x => x.Skip(1).Any()); 

我知道我可以把第一條語句放入if else子句。我也跑了一個快速測試。重複列表給我回1當我期待0,但它確實正確地呼籲我有一套我使用的重複的事實...

其他方法完全按照我的預期。下面是我用它來測試此數據集....

愚弄:

List<DupeCheckee> test = new List<DupeCheckee>{ 
    new DupeCheckee("test0", "test1"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test1", "test2"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test2", "test3"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test3", "test3"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test0", "test5"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test1", "test6"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test2", "test7"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test3", "test8"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test0", "test5"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test1", "test1"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test2", "test2"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test3", "test3"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test4", "test4"),//{ checkThis = "test", checkThat = "test1"} 

}; 

沒有愚弄......

 List<DupeCheckee> test2 = new List<DupeCheckee>{ 
    new DupeCheckee("test0", "test1"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test1", "test2"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test2", "test3"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test3", "test3"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test4", "test5"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test5", "test6"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test6", "test7"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test7", "test8"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test8", "test5"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test9", "test1"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test2", "test2"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test3", "test3"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test4", "test4"),//{ checkThis = "test", checkThat = "test1"} 

}; 
+1

將'using System.Linq;'添加到您的cs文件的頂部以使'GroupBy'工作。 – 2013-04-24 16:29:33

+0

是的。剛剛發現我錯過了它。謝謝。 – SoftwareSavant 2013-04-24 16:31:54

+2

Erm沒有愚弄有一個愚蠢的測試3,test3 – 2013-04-25 17:35:03

回答

30

您需要引用System.Linq(例如,using System.Linq

那麼你可以做

var dupes = dupList.GroupBy(x => new {x.checkThis, x.checkThat}) 
        .Where(x => x.Skip(1).Any()); 

這會給你組的所有副本

然後重複該測試將

var hasDupes = dupList.GroupBy(x => new {x.checkThis, x.checkThat}) 
        .Where(x => x.Skip(1).Any()).Any(); 

甚至打電話ToList()ToArray()強制結果的計算,然後你可以檢查dupe並檢查它們。

如..

var dupes = dupList.GroupBy(x => new {x.checkThis, x.checkThat}) 
        .Where(x => x.Skip(1).Any()).ToArray(); 
if (dupes.Any()) { 
    foreach (var dupeList in dupes) { 
    Console.WriteLine(string.Format("checkThis={0},checkThat={1} has {2} duplicates", 
         duplist.Key.checkThis, 
         duplist.Key.checkThat, 
         duplist.Count() - 1)); 
    } 

} 

或者

var dupes = dupList.Select((x, i) => new { index = i, value = x}) 
        .GroupBy(x => new {x.value.checkThis, x.value.checkThat}) 
        .Where(x => x.Skip(1).Any()); 

,給你其中每組的每個項目存儲原始指數在屬性index和項目中的屬性組value

+0

我真的很期待看看這個物品是否有任何瑕疵。這將是很好的,有幾個'列表'與他們所有的重複...這將是很好,如果用戶想要稍後刪除它們,但我真的只是想檢查列表是否有欺騙。 – SoftwareSavant 2013-04-25 13:15:24

+0

@DmainEvent這是什麼?如果你想檢查是否有任何愚蠢行爲,只需檢查'dupes.Any()'如果爲true,那麼有重複記錄 – 2013-04-25 16:02:42

+0

你可以看看我的解決方案,看看你是否檢測到我的解決方案有任何缺陷。我嘗試了你的和我的,我的看起來很好......不確定你的。 – SoftwareSavant 2013-04-25 16:52:05

0

做一個SELECT DISTINCT使用LINQ,例如How can I do SELECT UNIQUE with LINQ?

然後比較不同結果與非顯着結果的計數。如果列表中有雙打,這會給你一個布爾值。

此外,你可以嘗試使用一個字典,這將保證密鑰是唯一的。

+0

如果他想用「GroupBy」做一些事情是更好的方法。 – 2013-04-24 16:30:14

+0

@Daniel將它作爲答案發布,以便我可以對其進行修改,用戶可以將其標記爲答案! – MatthewMartin 2013-04-24 16:34:09

1

我認爲這是你要找的東西:

List<dupeChecke> duplicates = dupeList.GroupBy(x => x) 
            .SelectMany(g => g.Skip(1)); 
+1

只有當dupeCheckee的equals檢查標識實例爲等於「checkThis」和「checkThat」相等的地方。 – 2013-04-24 16:41:55

+0

@BVVale:沒注意到他想把它分解得更遠!您的評論upvoted。 – 2013-04-24 17:41:45

0

對於內存對象,我總是使用LINQ方法將一個比較器添加到解決方案中。

public class dupeCheckee 
{ 
    public string checkThis { get; set; } 
    public string checkThat { get; set; } 

    dupeCheckee(string val, string val2) 
    { 
     checkThis = val; 
     checkThat = val2; 
    } 

    public class Comparer : IEqualityComparer<dupeCheckee> 
    { 
     public bool Equals(dupeCheckee x, dupeCheckee y) 
     { 
      if (x == null || y == null) 
       return false; 

      return x.CheckThis == y.CheckThis && x.CheckThat == y.CheckThat; 
     } 

     public int GetHashCode(dupeCheckee obj) 
     { 
      if (obj == null) 
       return 0; 

      return (obj.CheckThis == null ? 0 : obj.CheckThis.GetHashCode())^
       (obj.CheckThat == null ? 0 : obj.CheckThat.GetHashCode()); 
     } 
    } 
} 

現在,我們可以調用

List<dupeCheckee> dupList = new List<dupeCheckee>(); 
dupList.Add(new dupeCheckee("test1", "value1")); 
dupList.Add(new dupeCheckee("test2", "value1")); 
dupList.Add(new dupeCheckee("test3", "value1")); 
dupList.Add(new dupeCheckee("test1", "value1"));//dupe 
dupList.Add(new dupeCheckee("test2", "value1"));//dupe... 
dupList.Add(new dupeCheckee("test4", "value1")); 
dupList.Add(new dupeCheckee("test5", "value1")); 
dupList.Add(new dupeCheckee("test1", "value2"));//not dupe 

var distinct = dupList.Distinct(dupeCheckee.Comparer); 
+0

這是得到一個明確的名單,但我期待弄清楚,如果我的名單有欺騙。 – SoftwareSavant 2013-04-25 13:10:26

0

的時候有任何重複在所有我喜歡用這個會知道。可以說你有一個字符串,並想知道是否有任何重複的字母。這是我使用的。

string text = "this is some text"; 

var hasDupes = text.GroupBy(x => x).Any(grp => grp.Count() > 1); 

如果你想知道有多少重複,不管重複是什麼,使用這個。

var totalDupeItems = text.GroupBy(x => x).Count(grp => grp.Count() > 1); 

因此,舉例來說, 「這是一些文本」 有這...

總的字母T:3

總信我:2

總的字母s :3

總字母e:2

所以可變totalDupeItems將等於4。有4種不同的副本。

如果你想獲得總量的dupe物品,不管是什麼愚蠢的,然後使用它。

var totalDupes = letters.GroupBy(x => x).Where(grp => grp.Count() > 1).Sum(grp => grp.Count()); 

所以變量totalDupes將是10.這是每個類型的總共重複的項目加在一起。

5

有工作方案的數額巨大,但我認爲,未來的解決方案將更加透明和易於理解,那麼所有上述:

var hasDuplicatedEntries = ListWithPossibleDuplicates 
            .GroupBy(YourGroupingExpression) 
            .Any(e => e.Count() > 1); 
if(hasDuplicatedKeys) 
{ 
    // Do what ever you want in case when list contains duplicates 
} 
0

如果出現任何重複拋出異常。字典本身檢查密鑰。 這是最簡單的方法。

try 
{ 
    dupList.ToDictionary(a=>new {a.checkThis,a.checkThat}); 
} 
catch{ 
//message: list items is not uniqe 
}