A separate list of lists in which lists contain the same values, but in a different order

I have a list:

var list = new List<List<int>>(); 

which may contain

 list[0] = {1, 2, 3, 4} list[1] = {3, 1, 2, 4} list[2] = {2, 1, 7, 3} 

How to identify a duplicate between [0] and [1] and delete one of them? C-sharp code.

This is not really int, but it should not change.

+7
source share
4 answers

You can write your own implementation of IEqualityComparer<List<int>> . For GetHashCode() it will simply return the XOR of all the hash codes of the items in the list. For Equals() it will create a new HashSet<int> from the first list and call HashSet<T>.SetEquals , moving to the second list. This suggests that there will be no duplicate elements, mind you. (Otherwise, {1, 1, 2} will be equal to {1, 2, 2}, but has a different hash code.)

Once you have come this far, you can use Distinct :

 var distinct = list.Distinct(new CustomEqualityComparer()); 

As an alternative approach, could you use HashSet<T> as the type of your collection to start with? Then it is really easy:

 var distinct = sets.Distinct(HashSet<int>.CreateSetComparer()); 

If you need lists as input, but they can handle the sets:

 var distinct = list.Select(x => new HashSet<int>(x)) .Distinct(HashSet<int>.CreateSetComparer()); 
+10
source

Jon Skeet's euqality comparer is mentioned here (his advice on working with HashSets also has a place to start, of course):

  public class EnumerableComparer<T> : IEqualityComparer<IEnumerable<T>> where T : IComparable<T> { public bool Equals(IEnumerable<T> first, IEnumerable<T> second) { if (first == second) return true; if ((first == null) || (second == null)) return false; return new HashSet<T>(first).SetEquals(second); } public int GetHashCode(IEnumerable<T> enumerable) { return enumerable.OrderBy(x => x) .Aggregate(17, (current, val) => current*23 + val.GetHashCode()); } } 

So you would do something like:

 list.Distinct(new EnumerableComparer()); 

If the items are not guaranteed to be unique, use the IEqualityComparer , which I posted here: Compare two collections for equality regardless of the order of the items in them

(In previous editions, I mistakenly placed IEqulityComparer, which compares between two lists of lists - it can be very useful when working with sections, but this is another topic)

+5
source
 list[1] = list[1].Except(list[0]).ToList(); 

This solution is under the assumption that we need to remove duplicates of int from the arrays list[0] and list[1] . Other answers relate to the case of deleting arrays that contain the same set of indices.

+1
source
 boolean compareLists(list1, list2) { // Early rejection if (list1.size != list2.size) { return false; } // Sort lists and compare each item sorted1 = sort(list1.clone()); sorted2 = sort(list2.clone()); for (int i=0; i<list1.size; ++i) { if (sorted1[i]!=sorted2[i]) { return false; } } return true; } 
+1
source

All Articles