Как удалить повторяющийся список в List‹List‹int››

У меня List<List<int>>, например у List<List<int>> есть {{1,2,3}, {1,1,2,}, {1,2,3}}.

Я хочу удалить дубликат в этом: Результат должен быть: {{1,2,3}, {1,1,2}}

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

Я не хочу полностью перебирать список, чтобы найти дубликаты, поскольку это не оптимально.


person Sahil Sharma    schedule 05.07.2015    source источник
comment
Я не понимаю последнюю фразу. В конце концов, вам просто нужно посмотреть на каждый элемент (независимо от того, скрыт ли он за каким-то кодом LINQ или явным).   -  person Christian.K    schedule 05.07.2015


Ответы (5)


Попробуй это:

List<List<int>> lst = new List<List<int>>()
{
    new List<int> {1,2,3},
    new List<int> {1,1,2}, 
    new List<int> {1,2,3}
};

var result = lst.GroupBy(c => String.Join(",", c)).Select(c => c.First().ToList()).ToList();
person Salah Akbari    schedule 05.07.2015

Вы можете реализовать класс EqualityComparer и использовать его в методе Distinct LINQ.

public class CustomEqualityComparer : IEqualityComparer<List<int>>
{
     public bool Equals(List<int> x, List<int> y)
     {
         if (x.Count != y.Count)
             return false;
         for (int i = 0; i < x.Count; i++)
         {
            if (x[i] != y[i])
                return false;
         }
         return true;
     }

     public int GetHashCode(List<int> obj)
     {
         return 0;
     }
}

и использовать его так

public static void Main(string[] args)
{
    var list = new List<List<int>>() { new List<int> { 1, 1, 2 }, new List<int> { 1, 2, 3 }, new List<int> { 1, 1, 2 } };
    var res = list.Distinct(new CustomEqualityComparer());
    Console.WriteLine("Press any key to continue.");
    Console.ReadLine();
}
person farid bekran    schedule 05.07.2015
comment
Если вы не знаете количество коллекции, т. е. всегда ли она очень мала, вам следует реализовать GetHashCode. Используется методом Distinct. - person Dzienny; 06.07.2015

Это очень просто:

List<List<int>> lst = new List<List<int>>()
{
    new List<int> {1,2,3},
    new List<int> {1,1,2,}, 
    new List<int> {1,2,3},
};

var result =
    lst
        .Where((xs, n) =>
            !lst
                .Skip(n + 1)
                .Any(ys => xs.SequenceEqual(ys)))
        .ToList();

Я получаю этот результат:

результат

person Enigmativity    schedule 05.07.2015

То, что вы хотите, сложнее простого сравнения. С моей точки зрения, вы должны создать новый тип/класс, например IntegerCollection : ICollection

Затем вы должны реализовать Equals таким образом:

bool Equals(IntegerCollection col) {    if(this.Count() != col.Count())
      return false;

   if(this.Sum() != col.Sum())
      return false;

   for(int i = 0; i < this.Count(); i++)    {
      if(this[i]==col[i]){
         continue;
      }else{
         return false;
      }    }

   return true; }

И наконец

List<IntegerCollection> collections = new List<IntegerCollection> {
     new IntegerCollection({1,2,3}),
     new IntegerCollection({1,1,2}),
     new IntegerCollection({1,2,3})};
var distincts = collections.Distinct();
person Alberto León    schedule 05.07.2015
comment
Некоторый совет в F #, у вас есть эта опция, основанная на туплах. - person Alberto León; 05.07.2015

Используя @farid CustomEqualityComparer, вы также можете использовать HashSet:

List<List<int>> RemoveDuplicates(IEnumerable<List<int>> values)
{
    return new HashSet<List<int>>(values,new CustomEqualityComparer()).ToList();
}
person Kevin    schedule 05.07.2015