2013-04-24 81 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 
}