У меня есть список объектов Tuple<string,string>
, и я хочу удалить дубликаты, где, например, кортежи (a,b)
и (b,a)
считаются одинаковыми (это ребра графа). Что такое nice Способ для этого?Удаление дубликатов из списка кортежей
ответ
Вам нужно создать компаратор, который может сравнить кортежи таким образом, что порядок элементов doens't дело:
public class UnorderedTupleComparer<T> : IEqualityComparer<Tuple<T, T>>
{
private IEqualityComparer<T> comparer;
public UnorderedTupleComparer(IEqualityComparer<T> comparer = null)
{
this.comparer = comparer ?? EqualityComparer<T>.Default;
}
public bool Equals(Tuple<T, T> x, Tuple<T, T> y)
{
return comparer.Equals(x.Item1, y.Item1) && comparer.Equals(x.Item2, y.Item2) ||
comparer.Equals(x.Item1, y.Item2) && comparer.Equals(x.Item1, y.Item2);
}
public int GetHashCode(Tuple<T, T> obj)
{
return comparer.GetHashCode(obj.Item1)^comparer.GetHashCode(obj.Item2);
}
}
Обратите внимание, что исключительный или хэш-коды - это операция, которая будет иметь тот же результат независимо от порядка операндов, что делает его желательным здесь (но не в большинстве алгоритмов генерации хеш-кода, так как обычно это нежелательное свойство). Что касается Equals
, просто нужно проверить оба возможных сопряжения.
После того, как вы есть, что вы можете сделать:
var query = data.Distinct(new UnorderedTupleComparer<string>());
Вы, возможно, потребуется создать класс, который реализует IEqualityComparer<Tuple<string, string>>
:
public class TupleComparer : IEqualityComparer<Tuple<string, string>>
{
public bool Equals(Tuple<string, string> x, Tuple<string, string> y)
{
if (ReferenceEquals(x, y))
{
return true;
}
if (ReferenceEquals(x, null) || ReferenceEquals(y, null))
{
return false;
}
if (x.Item1.Equals(y.Item2) && x.Item2.Equals(y.Item1))
{
return true;
}
return x.Item1.Equals(y.Item1) && x.Item2.Equals(y.Item2);
}
public int GetHashCode(Tuple<string, string> tuple)
{
// implementation
}
}
Вы можете затем использовать метод Distinct()
LINQ так:
List<Tuple<string, string>> list = new List<Tuple<string, string>> { Tuple.Create("a", "b"), Tuple.Create("a", "c"), Tuple.Create("b", "a") };
var result = list.Distinct(new TupleComparer());
Почему downvote, это делает именно то, о чем попросил – CSharpie
попробовать с использованием словаря и макетирование ключ, обозначает каждый кортеж. у вас есть символ, который НЕ будет отображаться в ваших строках, который вы можете использовать в качестве разделителя? Я выбрал «:» в этом примере:
static void Main(string[] args)
{
// original list of data
var list = new List<Tuple<string, string>> { };
list.Add(new Tuple<string, string>("a", "b"));
list.Add(new Tuple<string, string>("b", "a"));
// dictionary to hold unique tuples
var dict = new Dictionary<string, Tuple<string, string>>();
foreach (var item in list)
{
var key1 = string.Concat(item.Item1, ":", item.Item2);
var key2 = string.Concat(item.Item2, ":", item.Item1);
// if dict doesnt contain tuple, add it.
if (!dict.ContainsKey(key1) && !dict.ContainsKey(key2))
dict.Add(key1, item);
}
// print unique tuples
foreach (var item in dict)
{
var tuple = item.Value;
Console.WriteLine(string.Concat(tuple.Item1, ":", tuple.Item2));
}
Console.ReadKey();
}
Живой Код: https://dotnetfiddle.net/LUErFj
Делают это с помощью сортировки пару Tuple первый, а затем сделать Distinct:
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
static List<Tuple<string, string>> myList = new List<Tuple<string, string>>()
{
Tuple.Create<string, string>("A", "B"),
Tuple.Create<string, string>("B", "A"), // duplicate
Tuple.Create<string, string>("C", "B"),
Tuple.Create<string, string>("C", "B"), // duplicate
Tuple.Create<string, string>("A", "D")
};
public static void Main()
{
myList
.Select(x => new[] { x.Item1, x.Item2 }.OrderBy(s => s).ToArray())
.Select(x => Tuple.Create<string,string>(x[0], x[1]))
.Distinct()
.Dump();
}
}
Выход:
Dumping object(System.Linq.<DistinctIterator>d__81`1[Tuple`2[String,String]])
[
{
Item1 : A
Item2 : B
ToString(): (A, B)
},
{
Item1 : B
Item2 : C
ToString(): (B, C)
},
{
Item1 : A
Item2 : D
ToString(): (A, D)
}
]
Обратите внимание, что это может привести к возврату кортежа, который не находится в исходной последовательности; если вход является '{" b "," a "}', тогда он вернет '{" a "," b "}', а не '{" b "," a "}' на выходе. – Servy
@Servy Да, но вот как я понял вопрос. Если нужно сохранить исходные элементы, я вернусь к dotnetfiddle.net и сделаю вторую версию. –
Он хочет, чтобы пары, у которых значения в обратном порядке считаются равными, но это не обязательно означает, что это нормально для возврата элемента, который не находится в исходном наборе. Это может быть хорошо, но это может быть не так, это не определено. – Servy
Для сохранения оригинала, используйте group by вместо Distinct, чтобы мы могли получить доступ к первому элементу группы:
Живой код: https://dotnetfiddle.net/LYZItb
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
static List<Tuple<string, string>> myList = new List<Tuple<string, string>>()
{
Tuple.Create<string, string>("B", "A"),
Tuple.Create<string, string>("A", "B"), // duplicate
Tuple.Create<string, string>("C", "B"),
Tuple.Create<string, string>("C", "B"), // duplicate
Tuple.Create<string, string>("A", "D"),
Tuple.Create<string, string>("E", "F"),
Tuple.Create<string, string>("F", "E"), // duplicate
};
public static void Main()
{
var result =
from y in
from x in myList
select new { Original = x, SortedPair = new[] { x.Item1, x.Item2 }.OrderBy(s => s).ToArray() }
group y by new { NormalizedTuple = Tuple.Create<string,string>(y.SortedPair[0], y.SortedPair[1]) } into grp
select new { Pair = grp.Key.NormalizedTuple, Original = grp.First().Original };
foreach(var item in result)
{
Console.WriteLine("Pair: {0} {1}", item.Original.Item1, item.Original.Item2);
}
}
}
Выход:
Pair: B A
Pair: C B
Pair: A D
Pair: E F
- 1. Удаление дубликатов членов из списка кортежей
- 2. Haskell: Удаление дубликатов кортежей из списка?
- 3. Удаление дубликатов кортежей из списка списка в Python
- 4. Удаление дубликатов из списка кортежей на основе одного из значений
- 5. Удаление кортежей из списка
- 6. Удаление дубликатов из списка
- 7. Удаление дубликатов из списка
- 8. Pig - удаление дубликатов кортежей из сумки
- 9. Rails mysql Удаление дубликатов кортежей
- 10. Удаление элемента из списка кортежей
- 11. Удаление элементов из списка кортежей
- 12. Удаление перестановок из списка кортежей
- 13. Удаление дубликатов кортежей в списке в Haskell
- 14. Python: Удаление дубликатов из списка
- 15. Удаление дубликатов из выпадающего списка
- 16. Удаление дубликатов из Связанного списка
- 17. удаление дубликатов из вложенного списка
- 18. удаление дубликатов из списка C#
- 19. Удаление дубликатов наборов из списка
- 20. Удаление дубликатов из списка общего
- 21. Удаление дубликатов из выпадающего списка
- 22. удаление дубликатов из списка C++
- 23. Удаление дубликатов из отсортированного списка
- 24. Удаление дубликатов сообщений из списка
- 25. Удаление дубликатов из связанного списка
- 26. Удаление сопряженных кортежей из списка в Haskell
- 27. Удаление всех вхождений элемента из списка кортежей
- 28. удаление дубликатов из списка моделей Джанго
- 29. Удаление дубликатов из списка в MVC 4
- 30. Удаление подмножеств и дубликатов из списка?
Не используя работа EqualityComparer, как показано в этой статье SO http://stackoverflow.com/questions/17275727/find-and-deletes-duplicates-in-list-of-tuples-in-c-sharp –
Нужно ли сохранять упорядочение ваших кортежей, например вы могли бы отсортировать их все так, чтобы первый <= второй? Это упростило бы удаление дубликатов, например. используя Distinct, как в ответе здесь. – Rup
Нет заказа не имеет значения – Cemre