Как получить отчетливый результат для списка массивов? - PullRequest
1 голос
/ 09 января 2020

У меня есть список массива длинных типов.

List<ulong[]> TestList = new List<ulong[]>();

, и список содержит следующие элементы.

{1,2,3,4,5,6},
{2,3,4,5,6,7},
{3,4,5,6,7,8},
{1,2,3,4,5,6}

и ожидаемый отчетливый результат

{1,2,3,4,5,6},
{2,3,4,5,6,7},
{3,4,5,6,7,8}

Поэтому я пытаюсь сделать следующее, но это бесполезно.

TestList = TestList.Distinct().ToList();

Нужен ли мне какой-то специальный компаратор для получения отдельного списка?

Ответы [ 4 ]

6 голосов
/ 09 января 2020

Distinct() использует проверку равенства по умолчанию, которая для массивов является ссылочным равенством. Он не проверяет содержимое массива на равенство.

Если вы хотите это сделать, вам потребуется перегрузка Distinct(), которая принимает IEqualityComparer<T>. Это позволяет настроить поведение, чтобы определить, равны ли два элемента.

Для сравнения массивов IStructuralEquatable и друзья уже выполняют тяжелую работу. Вы можете обернуть его просто так:

sealed class StructuralComparer<T> : IEqualityComparer<T>
{
    public static IEqualityComparer<T> Instance { get; } = new StructuralComparer<T>();

    public bool Equals(T x, T y)
        => StructuralComparisons.StructuralEqualityComparer.Equals(x, y);

    public int GetHashCode(T obj)
        => StructuralComparisons.StructuralEqualityComparer.GetHashCode(obj);
}

Затем используйте его в вызове Distinct() следующим образом:

TestList = TestList.Distinct(StructuralComparer<ulong[]>.Instance).ToList();
2 голосов
/ 09 января 2020
List<ulong[]> TestList = new List<ulong[]>() {
    new ulong[]{ 1,2,3,4,5,6},
    new ulong[]{ 2,3,4,5,6,7},
    new ulong[]{ 3,4,5,6,7,8},
    new ulong[]{ 1,2,3,4,5,6}
};

var result = TestList.GroupBy(x => String.Join(",", x))
                     .Select(x => x.First().ToArray())
                     .ToList();
1 голос
/ 09 января 2020

Вам нужно предоставить средство сравнения равенства, реализация по умолчанию не знает, как сравнивать массивы long (он использует ссылочное равенство):

class LongArrayComparer : EqualityComparer<long[]> 
{
    public override bool Equals(long[] a1, long[] a2)
    {
        if (a1 == null && a2 == null)
            return true;
        else if (a1 == null || a2 == null)
            return false;

        return a1.SequenceEqual(a2);
    }

    public override int GetHashCode(long[] arr)
    {
        long hCode = arr.Aggregate(0, (acc, it) => acc ^ it);
        return hCode.GetHashCode();
    }
}

Затем используйте его:

TestList = TestList.Distinct(new LongArrayComparer()).ToList();
0 голосов
/ 09 января 2020

Вы можете реализовать IEqualityComparer

public class IntArrayComparer : IEqualityComparer<string[]>
{
    public bool Equals(int[] x, int[] y)
    {
        var shared = x.Intersect(y);
        return x.Length == y.Length && shared.Count() == x.Length;;
    }

    public int GetHashCode(int[] obj)
    {
        int hashCode=obj.Length;
        for(int i=0;i<obj.Length;++i)
        {
          hashCode=unchecked(hashCode*314159 +obj[i]);
        }
        return hashCode;
    }
}

Затем можете реализовать его:

TestList = TestList.Distinct(new IntArrayComparer()).ToList();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...