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

Найти и удалить дубликаты в списке кортежей в С#

Мне нужно найти и удалить дубликаты из списка кортежей. В принципе, моя структура сделана так:

List<Tuple<string, string>> myList = new List<Tuple<string, string>>();

****

private void FillStructure()
{
     myList.Add(Tuple.Create<string, string>("A", "B"));
     myList.Add(Tuple.Create<string, string>("A", "C"));
     myList.Add(Tuple.Create<string, string>("C", "B"));
     myList.Add(Tuple.Create<string, string>("C", "B"));    // Duplicate
     myList.Add(Tuple.Create<string, string>("A", "D"));

     FindAndRemoveDuplicates(myList);
}

private void FindAndRemoveDuplicates(List<Tuple<string, string>> myList)
{
        // how can I perform this ?
}

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

4b9b3361

Ответ 1

Вы можете использовать Distinct() метод LINQ, например:

myList = myList.Distinct().ToList();

Обратите внимание, что это приведет к повторному созданию списка, а не к удалению дубликатов.

Ответ 2

Вы можете использовать HashSet для этих целей (http://msdn.microsoft.com/en-us/library/bb359438.aspx)

class SameTuplesComparer<T1, T2> : EqualityComparer<Tuple<T1, T2>> 
{
   public override bool Equals(Tuple<T1, T2> t1, Tuple<T1, T2> t2)
   {
      return t1.Item1.Equals(t2.Item1) && t1.Item2.Equals(t2.Item2)
   }


   public override int GetHashCode(Tuple<T1, T2> t)
   {
     return base.GetHashCode();
   }
}

Итак, если вы пишете свой собственный сравнитель, вы можете сравнивать строки немного по-другому (например, не caseensetive):

class SameStringTuplesComparer: EqualityComparer<Tuple<string, string>> 
{
   public override bool Equals(Tuple<string, string> t1, Tuple<string, string> t2)
   {
      return t1.Item1.Equals(t2.Item1, StringComparison.CurrentCultureIgnoreCase) && t1.Item2.Equals(t2.Item2, StringComparison.CurrentCultureIgnoreCase)
   }


   public override int GetHashCode(Tuple<string, string> t)
   {
     return base.GetHashCode();
   }
}

Затем в коде:

var hashSet = new HashSet<Tuple<string, string>>(list, new SameTuplesComparer());

Или без вашего собственного сравнения:

var hashSet = HashSet<Tuple<string, string>>(list);

Теперь вы можете добавлять элементы в hashSet, и все элементы будут уникальными. После того, как вы добавили элементы, вы можете снова преобразовать их в список:

var uniquedList = hashSet.ToList();

Или просто используйте list.Distinct().ToList()

Ответ 3

Использовать метод distinct():

myList.Distinct().ToList();

Ответ 4

Если вы хотите получить решение, которое вносит изменения в список, вы можете использовать HashSet<T> (или для старых фреймворков a Dictionary<Tuple<string, string>, object> и игнорировать значение):

var existing = new HashSet<Tuple<string, string>>();

for (int i = myList.Count - 1; i >= 0; i--)
{
    if (existing.Contains(myList[i]))
    {
        myList.RemoveAt(i);
    }
    else
    {
        existing.Add(myList[i]);
    }
}

Мы рассчитываем назад без использования итератора (в противном случае вы получите ошибки, изменяющие список во время итерации).

HashSet<T> также имеет перегрузки для переопределения равенства, если вам это нужно.

Лично я хотел бы получить ответ dasblinkenlight для удобства чтения.