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

Jim*_*her 7 c# list distinct

我有一个清单:

var list = new List<List<int>>();
Run Code Online (Sandbox Code Playgroud)

哪个可以包含

list[0] = {1, 2, 3, 4}
list[1] = {3, 1, 2, 4}
list[2] = {2, 1, 7, 3}
Run Code Online (Sandbox Code Playgroud)

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

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

Jon*_*eet 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());
Run Code Online (Sandbox Code Playgroud)

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

var distinct = sets.Distinct(HashSet<int>.CreateSetComparer());
Run Code Online (Sandbox Code Playgroud)

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

var distinct = list.Select(x => new HashSet<int>(x))
                   .Distinct(HashSet<int>.CreateSetComparer());
Run Code Online (Sandbox Code Playgroud)


Oha*_*der 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());
        }
    }
Run Code Online (Sandbox Code Playgroud)

所以你要做的事情如下:

list.Distinct(new EnumerableComparer());
Run Code Online (Sandbox Code Playgroud)

如果不保证元素是唯一的 - 使用IEqualityComparer我在此处发布的内容: 比较两个集合的相等性,而不管它们中的项目顺序如何

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