又是一个比较列表的问题。
List<MyType> list1;
List<MyType> list2;
我需要检查它们是否具有相同的元素,而不管它们在列表中的位置。每个MyType对象可以在列表中出现多次。是否有一个内置函数来检查这个?如果我保证每个元素在列表中只出现一次呢?
编辑:伙计们,谢谢你们的回答,但我忘了补充一些东西,每个元素的出现次数应该是相同的两个列表。
又是一个比较列表的问题。
List<MyType> list1;
List<MyType> list2;
我需要检查它们是否具有相同的元素,而不管它们在列表中的位置。每个MyType对象可以在列表中出现多次。是否有一个内置函数来检查这个?如果我保证每个元素在列表中只出现一次呢?
编辑:伙计们,谢谢你们的回答,但我忘了补充一些东西,每个元素的出现次数应该是相同的两个列表。
当前回答
如上所述,这个问题模棱两可。声明:
... 它们都有相同的元素,不管它们在列表中的位置如何。 每个MyType对象可以在列表中出现多次。
没有指示是否要确保两个列表具有相同的对象集,还是具有相同的不同的对象集。
如果你想确保集合有完全相同的成员集,不管顺序如何,你可以使用:
// lists should have same count of items, and set difference must be empty
var areEquivalent = (list1.Count == list2.Count) && !list1.Except(list2).Any();
如果你想确保两个集合有相同的不同的成员集(其中任何一个的重复都被忽略),你可以使用:
// check that [(A-B) Union (B-A)] is empty
var areEquivalent = !list1.Except(list2).Union( list2.Except(list1) ).Any();
使用集合操作(Intersect、Union、Except)比使用Contains等方法更有效。在我看来,它也更好地表达了您的查询的期望。
编辑:既然你已经澄清了你的问题,我可以说你想使用第一种形式——因为重复很重要。这里有一个简单的例子来证明你得到了你想要的结果:
var a = new[] {1, 2, 3, 4, 4, 3, 1, 1, 2};
var b = new[] { 4, 3, 2, 3, 1, 1, 1, 4, 2 };
// result below should be true, since the two sets are equivalent...
var areEquivalent = (a.Count() == b.Count()) && !a.Except(b).Any();
其他回答
如上所述,这个问题模棱两可。声明:
... 它们都有相同的元素,不管它们在列表中的位置如何。 每个MyType对象可以在列表中出现多次。
没有指示是否要确保两个列表具有相同的对象集,还是具有相同的不同的对象集。
如果你想确保集合有完全相同的成员集,不管顺序如何,你可以使用:
// lists should have same count of items, and set difference must be empty
var areEquivalent = (list1.Count == list2.Count) && !list1.Except(list2).Any();
如果你想确保两个集合有相同的不同的成员集(其中任何一个的重复都被忽略),你可以使用:
// check that [(A-B) Union (B-A)] is empty
var areEquivalent = !list1.Except(list2).Union( list2.Except(list1) ).Any();
使用集合操作(Intersect、Union、Except)比使用Contains等方法更有效。在我看来,它也更好地表达了您的查询的期望。
编辑:既然你已经澄清了你的问题,我可以说你想使用第一种形式——因为重复很重要。这里有一个简单的例子来证明你得到了你想要的结果:
var a = new[] {1, 2, 3, 4, 4, 3, 1, 1, 2};
var b = new[] { 4, 3, 2, 3, 1, 1, 1, 4, 2 };
// result below should be true, since the two sets are equivalent...
var areEquivalent = (a.Count() == b.Count()) && !a.Except(b).Any();
如果你想让它们真正相等(即相同的项目和每个项目的相同数量),我认为最简单的解决方案是在比较之前进行排序:
Enumerable.SequenceEqual(list1.OrderBy(t => t), list2.OrderBy(t => t))
编辑:
下面是一个执行得更好的解决方案(大约快10倍),并且只需要相等,而不是icomcomparable:
public static bool ScrambledEquals<T>(IEnumerable<T> list1, IEnumerable<T> list2) {
var cnt = new Dictionary<T, int>();
foreach (T s in list1) {
if (cnt.ContainsKey(s)) {
cnt[s]++;
} else {
cnt.Add(s, 1);
}
}
foreach (T s in list2) {
if (cnt.ContainsKey(s)) {
cnt[s]--;
} else {
return false;
}
}
return cnt.Values.All(c => c == 0);
}
编辑2:
要将任何数据类型作为键处理(例如Frank Tzanabetis指出的可空类型),您可以创建一个版本,接受字典的比较器:
public static bool ScrambledEquals<T>(IEnumerable<T> list1, IEnumerable<T> list2, IEqualityComparer<T> comparer) {
var cnt = new Dictionary<T, int>(comparer);
...
除了Guffa的答案之外,您还可以使用这个变体来获得更简洁的符号。
public static bool ScrambledEquals<T>(this IEnumerable<T> list1, IEnumerable<T> list2)
{
var deletedItems = list1.Except(list2).Any();
var newItems = list2.Except(list1).Any();
return !newItems && !deletedItems;
}
这招对我很管用: 如果你正在比较依赖于单个实体(如ID)的两个对象列表,并且你想要匹配该条件的第三个列表,那么你可以执行以下操作:
var list3 = List1.Where(n => !List2.select(n1 => n1.Id).Contains(n.Id));
参考:MSDN - c#比较两个对象列表
试试这个! !
使用以下代码,您可以根据需要比较一个或多个字段以生成结果列表。结果列表将只包含已修改的项目。
// veriables been used
List<T> diffList = new List<T>();
List<T> gotResultList = new List<T>();
// compare First field within my MyList
gotResultList = MyList1.Where(a => !MyList2.Any(a1 => a1.MyListTField1 == a.MyListTField1)).ToList().Except(gotResultList.Where(a => !MyList2.Any(a1 => a1.MyListTField1 == a.MyListTField1))).ToList();
// Generate result list
diffList.AddRange(gotResultList);
// compare Second field within my MyList
gotResultList = MyList1.Where(a => !MyList2.Any(a1 => a1.MyListTField2 == a.MyListTField2)).ToList().Except(gotResultList.Where(a => !MyList2.Any(a1 => a1.MyListTField2 == a.MyListTField2))).ToList();
// Generate result list
diffList.AddRange(gotResultList);
MessageBox.Show(diffList.Count.ToString);