又是一个比较列表的问题。

List<MyType> list1;
List<MyType> list2;

我需要检查它们是否具有相同的元素,而不管它们在列表中的位置。每个MyType对象可以在列表中出现多次。是否有一个内置函数来检查这个?如果我保证每个元素在列表中只出现一次呢?

编辑:伙计们,谢谢你们的回答,但我忘了补充一些东西,每个元素的出现次数应该是相同的两个列表。


当前回答

除了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;          
}

其他回答

如果你不关心出现的次数,我会这样做。使用哈希集将比简单迭代提供更好的性能。

var set1 = new HashSet<MyType>(list1);
var set2 = new HashSet<MyType>(list2);
return set1.SetEquals(set2);

这将需要你重写. gethashcode()并在MyType上实现IEquatable<MyType>。

认为这应该是你想要的:

list1.All(item => list2.Contains(item)) &&
list2.All(item => list1.Contains(item));

如果你想要它是不同的,你可以把它改为:

list1.All(item => list2.Contains(item)) &&
list1.Distinct().Count() == list1.Count &&
list1.Count == list2.Count

试试这个! !

使用以下代码,您可以根据需要比较一个或多个字段以生成结果列表。结果列表将只包含已修改的项目。

// 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);

除了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;          
}

如果你想让它们真正相等(即相同的项目和每个项目的相同数量),我认为最简单的解决方案是在比较之前进行排序:

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);
  ...