Do it like that.
source .GroupBy(x => new {min = Math.Min(x.Id0, x.Id1), max = Math.Max(x.Id0, x.Id1)}) .Select(g => g.First());
Tested.
public void SillyTuplesTest() { List<Tuple<string, int, int>> source = new List<Tuple<string, int, int>>() { Tuple.Create("object0", 1, 2), Tuple.Create("object1",1, 2), Tuple.Create("object2",1, 3), Tuple.Create("object3",2, 1), Tuple.Create("object4",2, 3), Tuple.Create("object5",3, 2) }; var result = source .GroupBy(x => new { min = Math.Min(x.Item2, x.Item3), max = Math.Max(x.Item2, x.Item3) }) .Select(g => g.First()); foreach (Tuple<string, int, int> resultItem in result) { Console.WriteLine("{0} ({1}, {2})", resultItem.Item1, resultItem.Item2, resultItem.Item3); } }
results
object0 (1, 2) object2 (1, 3) object4 (2, 3)
For strings you can use:
source .GroupBy(x => string.Compare(x.Id0, x.Id1, false) < 0 ? new {min = x.Id0, max = x.Id1} : new {min = x.Id1, max = x.Id0}) .Select(g => g.First());
If you had an unknown number of rows, you can use the HashSet<string> as the key and SetComparer.
IEqualityComparer<HashSet<string>> comparer = HashSet<string>.CreateSetComparer(); source .GroupBy(x => new HashSet<string>(x.GetStrings()), comparer) .Select(g => g.First());