Подтвердить что ты не робот

С# удалить дубликаты из списка <List <int>>

У меня возникли проблемы с поиском наиболее эффективного алгоритма для удаления дубликатов из List<List<int>>, например (я знаю, что это выглядит как список int[], но просто делает это таким образом для визуальных целей:

my_list[0]= {1, 2, 3};
my_list[1]= {1, 2, 3};
my_list[2]= {9, 10, 11};
my_list[3]= {1, 2, 3};

Таким образом, выход будет

new_list[0]= {1, 2, 3};
new_list[1]= {9, 10, 11};

Сообщите мне, есть ли у вас какие-либо идеи. Я был бы очень признателен.

4b9b3361

Ответ 1

Построить пользовательский стиль EqualityComparer<List<int>>:

public class CusComparer : IEqualityComparer<List<int>>
{
    public bool Equals(List<int> x, List<int> y)
    {
        return x.SequenceEqual(y);
    }

    public int GetHashCode(List<int> obj)
    {
        int hashCode = 0;

        for (var index = 0; index < obj.Count; index++)
        {
            hashCode ^= new {Index = index, Item = obj[index]}.GetHashCode();
        }

        return hashCode;
    }
}

Затем вы можете получить результат, используя Distinct с помощью пользовательского метода сравнения:

var result = my_list.Distinct(new CusComparer());

Edit:

Включите индекс в метод GetHashCode, чтобы убедиться, что разные заказы не будут равны.

Ответ 2

    var finalList = lists.GroupBy(x => String.Join(",", x))
                         .Select(x => x.First().ToList())
                         .ToList();

Ответ 3

Эта простая программа делает то, что вы хотите:

using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApplication6
{
    class Program
    {
        static void Main(string[] args)
        {
            List<List<int>> lists = new List<List<int>>();

            lists.Add(new List<int> { 1, 2, 3 });
            lists.Add(new List<int> { 1, 2, 3 });
            lists.Add(new List<int> { 9, 10, 11 });
            lists.Add(new List<int> { 1, 2, 3 });

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

            foreach (var list in distinct)
            {
                foreach (var v in list)
                {
                    Console.Write(v + " ");
                }

                Console.WriteLine();
            }
        }
    }
}

Ответ 4

Вы можете использовать перегрузку LINQ Distinct, которая берет компаратор. Компаратор должен видеть, равны ли списки. Обратите внимание, что значение по умолчанию равно операциям списков не будет делать то, что вы действительно ищете, поэтому для сравнения вам нужно будет прокручивать каждый из них. Вот пример такого сравнения:

public class SequenceComparer<T> : IEqualityComparer<IEnumerable<T>>
{
    IEqualityComparer<T> itemComparer;
    public SequenceComparer()
    {
        this.itemComparer = EqualityComparer<T>.Default;
    }

    public SequenceComparer(IEqualityComparer<T> itemComparer)
    {
        this.itemComparer = itemComparer;
    }

    public bool Equals(IEnumerable<T> x, IEnumerable<T> y)
    {
        if (object.Equals(x, y))
            return true;
        if (x == null || y == null)
            return false;
        return x.SequenceEqual(y, itemComparer);
    }

    public int GetHashCode(IEnumerable<T> obj)
    {
        if (obj == null)
            return -1;
        int i = 0;
        return obj.Aggregate(0, (x, y) => x ^ new { Index = i++, ItemHash = itemComparer.GetHashCode(y) }.GetHashCode());
    }
}

Обновление:. У меня появилась идея использовать анонимный тип, чтобы сделать лучший хэш из ответа Cuong Le, и я LINQ-ified его и заставил его работать в моем классе.

Ответ 5

Для небольших наборов данных сравнение может быть полезно, но если у вас есть 1000 или более List > , то при попытке сравнить их все может занять много времени.

Я предлагаю вам вместо этого использовать ваши данные для создания отдельного дерева. Построение дерева будет намного быстрее, и когда вы закончите, вы всегда сможете вернуть свои данные в свою прежнюю структуру данных.