我正在寻找一种非常快速的方法来检查对象列表中的重复项。
我在考虑简单地循环遍历列表并以这种方式进行手动比较,但我认为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子句中。我也进行了快速测试。当我期待0时,重复列表给了我1但它确实正确地称我在我使用的其中一个集合中有重复的事实......
另一种方法完全按照我的预期进行。以下是我用来测试它的数据集....
愚弄:
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"}
};
答案 0 :(得分:36)
您需要引用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()
以强制计算结果,然后您可以检查欺骗并检查它们。
例如..
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
答案 1 :(得分:8)
有大量的工作解决方案,但我认为下一个解决方案将更加透明和易于理解,然后以上所有:
var hasDuplicatedEntries = ListWithPossibleDuplicates
.GroupBy(YourGroupingExpression)
.Any(e => e.Count() > 1);
if(hasDuplicatedEntries)
{
// Do what ever you want in case when list contains duplicates
}
答案 2 :(得分:1)
我认为这就是你要找的东西:
List<dupeChecke> duplicates = dupeList.GroupBy(x => x)
.SelectMany(g => g.Skip(1));
答案 3 :(得分:0)
选择与linq不同的选项,例如: How can I do SELECT UNIQUE with LINQ?
然后将不同结果的计数与非不同结果进行比较。如果列表有双打,那将给你一个布尔说法。
此外,您可以尝试使用字典,这将保证密钥是唯一的。
答案 4 :(得分:0)
对于内存对象,我总是使用Distinct
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);
答案 5 :(得分: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);
例如,&#34;这是一些文字&#34;有这个...
总共字母t:3总信件i:2
总共字母s:3 总共字母e:2因此变量totalDupeItems等于4.有4种不同的重复项。
如果您想获得欺骗物品的总量,无论这些物品是什么,请使用此物品。
var totalDupes = letters.GroupBy(x => x).Where(grp => grp.Count() > 1).Sum(grp => grp.Count());
因此变量totalDupes将为10.这是每个重叠类型的重复项总数。