不同的列表列表,其中列表包含相同的值但顺序不同

时间:2010-12-23 10:23:50

标签: c# list distinct

我有一份清单:

var list = new List<List<int>>();

可以包含

list[0] = {1, 2, 3, 4}
list[1] = {3, 1, 2, 4}
list[2] = {2, 1, 7, 3}

如何检测[0]和[1]之间的重复并删除其中一个?代码是c-sharp。

实际上它不是一个int,但这不应该改变这个问题。

4 个答案:

答案 0 :(得分:11)

您可以编写自己的IEqualityComparer<List<int>>实现。对于GetHashCode(),它只返回列表中元素的所有哈希码的XOR。对于Equals(),它会从第一个列表中创建一个新的HashSet<int>,并在其上调用HashSet<T>.SetEquals,并传入第二个列表。假设您没有重复的元素。 (否则{1,1,2}将等于{1,2,2}但具有不同的哈希码。)

到目前为止,您可以使用Distinct

var distinct = list.Distinct(new CustomEqualityComparer());

作为替代方法,您可以使用HashSet<T>作为收集类型吗?那么真的很容易

var distinct = sets.Distinct(HashSet<int>.CreateSetComparer());

如果您需要列表作为输入,但可以处理集合作为输出:

var distinct = list.Select(x => new HashSet<int>(x))
                   .Distinct(HashSet<int>.CreateSetComparer());

答案 1 :(得分:5)

以下是Jon Skeet所谈论的euqality比较器(当然,他关于与HashSets合作的建议也是当然的):

    public class EnumerableComparer<T> : IEqualityComparer<IEnumerable<T>> 
                                          where T : IComparable<T>
    {
        public bool Equals(IEnumerable<T> first, IEnumerable<T> second)
        {
            if (first == second)
                return true;
            if ((first == null) || (second == null))
                return false;

            return new HashSet<T>(first).SetEquals(second);
        }

        public int GetHashCode(IEnumerable<T> enumerable)
        {
            return enumerable.OrderBy(x => x)
              .Aggregate(17, (current, val) => current*23 + val.GetHashCode());
        }
    }

所以你会做类似的事情:

list.Distinct(new EnumerableComparer());

如果不保证元素是唯一的 - 请使用我在此处发布的IEqualityComparerComparing two collections for equality irrespective of the order of items in them

(在以前的编辑中,我错误地发布了一个IEqulityComparer,用于比较两个列表列表 - 在处理分区时可能非常有用,但这是一个不同的主题)

答案 2 :(得分:1)

list[1] = list[1].Except(list[0]).ToList();

这是解决方案,我们需要从数组list[0]list[1]中删除重复的int。其他答案正在处理删除包含相同内容集的数组的情况。

答案 3 :(得分:1)

boolean compareLists(list1, list2) {
  // Early rejection
  if (list1.size != list2.size) {
    return false;
  }

  // Sort lists and compare each item
  sorted1 = sort(list1.clone());
  sorted2 = sort(list2.clone());
  for (int i=0; i<list1.size; ++i) {
    if (sorted1[i]!=sorted2[i]) {
      return false;
    }
  }
  return true;
}