LINQ Differs from several properties in both directions

I am trying to filter a list of objects by two of their properties. An object can be deleted if there is a duplicate. And if the first property has the same value as the second property, and the second property has the same value as the first property.

Example:

object0: id0=1A, id1=2B object1: id0=1A, id1=2B object2: id0=1A, id1=3C object3: id0=2B, id1=1A object4: id0=2B, id1=3C object5: id0=3C, id1=2B 

So, the following happens: object0 deletes object1 and object 3 object4 deletes object5

Final result:

 object0: id0=1A, id1=2B object2: id0=1A, id1=3C object4: id0=2B, id1=3C 

Right now I have a FOR loop that does this, but I was wondering if there is a way to do this with linq? I tried using Distinct, DistinctBy and GroupBy. Do I need to make my own comparison for this?

+4
source share
2 answers

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()); 
+4
source

Create an extension method such as this:

 public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector) { var seenKeys = new HashSet<TKey>(); return source.Where(element => seenKeys.Add(keySelector(element))); } 

Then use it.

See how it works for you.

-one
source

Source: https://habr.com/ru/post/1496011/


All Articles