Blog coding and discussion of coding about JavaScript, PHP, CGI, general web building etc.

Saturday, November 26, 2016

Compare two List objects for equality, ignoring order

Compare two List objects for equality, ignoring order


Yet another list-comparing question.

List list1;  List list2;  

I need to check that they both have the same elements, regardless of their position within the list. Each MyType object may appear multiple times on a list. Is there a built-in function that checks this? What if I guarantee that each element appears only once in a list?

EDIT: Guys thanks for the answers but I forgot to add something, the number of occurrences of each element should be the same on both lists.

Answer by Brian Genisio for Compare two List objects for equality, ignoring order


Thinking this should do what you want:

list1.All(item => list2.Contains(item)) &&  list2.All(item => list1.Contains(item));  

if you want it to be distinct, you could change it to:

list1.All(item => list2.Contains(item)) &&  list1.Distinct().Count() == list1.Count &&  list1.Count == list2.Count  

Answer by recursive for Compare two List objects for equality, ignoring order


If you don't care about the number of occurrences, I would approach it like this. Using hash sets will give you better performance than simple iteration.

var set1 = new HashSet(list1);  var set2 = new HashSet(list2);  return set1.SetEquals(set2);  

This will require that you have overridden .GetHashCode() and implemented IEquatable on MyType.

Answer by Ani for Compare two List objects for equality, ignoring order


This is a slightly difficult problem, which I think reduces to: "Test if two lists are permutations of each other."

I believe the solutions provided by others only indicate whether the 2 lists contain the same unique elements. This is a necessary but insufficient test, for example {1, 1, 2, 3} is not a permutation of {3, 3, 1, 2} although their counts are equal and they contain the same distinct elements.

I believe this should work though, although it's not the most efficient:

static bool ArePermutations(IList list1, IList list2)  {     if(list1.Count != list2.Count)           return false;       var l1 = list1.ToLookup(t => t);     var l2 = list2.ToLookup(t => t);       return l1.Count == l2.Count          && l1.All(group => l2.Contains(group.Key) && l2[group.Key].Count() == group.Count());   }  

Answer by LBushkin for Compare two List objects for equality, ignoring order


As written, this question is ambigous. The statement:

... they both have the same elements, regardless of their position within the list. Each MyType object may appear multiple times on a list.

does not indicate whether you want to ensure that the two lists have the same set of objects or the same distinct set.

If you want to ensure to collections have exactly the same set of members regardless of order, you can use:

// lists should have same count of items, and set difference must be empty  var areEquivalent = (list1.Count == list2.Count) && !list1.Except(list2).Any();  

If you want to ensure two collections have the same distinct set of members (where duplicates in either are ignored), you can use:

// check that [(A-B) Union (B-A)] is empty  var areEquivalent = !list1.Except(list2).Union( list2.Except(list1) ).Any();  

Using the set operations (Intersect, Union, Except) is more efficient than using methods like Contains. In my opinion, it also better expresses the expectations of your query.

EDIT: Now that you've clarified your question, I can say that you want to use the first form - since duplicates matter. Here's a simple example to demonstrate that you get the result you want:

var a = new[] {1, 2, 3, 4, 4, 3, 1, 1, 2};  var b = new[] { 4, 3, 2, 3, 1, 1, 1, 4, 2 };    // result below should be true, since the two sets are equivalent...  var areEquivalent = (a.Count() == b.Count()) && !a.Except(b).Any();   

Answer by Guffa for Compare two List objects for equality, ignoring order


If you want them to be really equal (i.e. the same items and the same number of each item), I think that the simplest solution is to sort before comparing:

Enumerable.SequenceEqual(list1.OrderBy(t => t), list2.OrderBy(t => t))  

Edit:

Here is a solution that performs a bit better (about ten times faster), and only requires IEquatable, not IComparable:

public static bool ScrambledEquals(IEnumerable list1, IEnumerable list2) {    var cnt = new Dictionary();    foreach (T s in list1) {      if (cnt.ContainsKey(s)) {        cnt[s]++;      } else {        cnt.Add(s, 1);      }    }    foreach (T s in list2) {      if (cnt.ContainsKey(s)) {        cnt[s]--;      } else {        return false;      }    }    return cnt.Values.All(c => c == 0);  }  

Edit 2:

To handle any data type as key (for example nullable types as Frank Tzanabetis pointed out), you can make a version that takes a comparer for the dictionary:

public static bool ScrambledEquals(IEnumerable list1, IEnumerable list2, IEqualityComparer comparer) {    var cnt = new Dictionary(comparer);    ...  

Answer by Caedere for Compare two List objects for equality, ignoring order


In addition to Guffa's answer, you could use this variant to have a more shorthanded notation.

public static bool ScrambledEquals(this IEnumerable list1, IEnumerable list2)  {    var deletedItems = list1.Except(list2).Any();    var newItems = list2.Except(list1).Any();    return !newItems && !deletedItems;            }  

Answer by Haseeb Ahmed for Compare two List objects for equality, ignoring order


try this!!!

using following code you could compare one or many fields to generate a result list as per your need. result list will contain only modified item(s).

// veriables been used  List diffList = new List();  List gotResultList = new List();        // compare First field within my MyList  gotResultList = MyList1.Where(a => !MyList2.Any(a1 => a1.MyListTField1 == a.MyListTField1)).ToList().Except(gotResultList.Where(a => !MyList2.Any(a1 => a1.MyListTField1 == a.MyListTField1))).ToList();  // Generate result list  diffList.AddRange(gotResultList);    // compare Second field within my MyList  gotResultList = MyList1.Where(a => !MyList2.Any(a1 => a1.MyListTField2 == a.MyListTField2)).ToList().Except(gotResultList.Where(a => !MyList2.Any(a1 => a1.MyListTField2 == a.MyListTField2))).ToList();  // Generate result list  diffList.AddRange(gotResultList);      MessageBox.Show(diffList.Count.ToString);  

Answer by Shaun Luttin for Compare two List objects for equality, ignoring order


Answer

Combine Count, Except, and Any like this. As Bioukh mentioned, it is faster to Count first.

public static bool AreTheSameIgnoringOrder(List x, List y)  {      return x.Count() == y.Count()           && !x.Except(y).Any()          && !y.Except(x).Any(); // re: Servy's comment.  }  

Demo

Here is a fiddle to demonstrate.

using System;  using System.Collections.Generic;  using System.Linq;    public class Program  {      public static void Main()      {          var x = new List() { "a", "b", "c"};            var result1 = AreTheSameIgnoringOrder(x, new List() { "c", "b", "a"});          Console.WriteLine(result1);            var result2 = AreTheSameIgnoringOrder(x, new List() { "c", "b", "a", "b" });          Console.WriteLine(result2);      }        public static bool AreTheSameIgnoringOrder(List x, List y)      {          return x.Count() == y.Count()               && !x.Except(y).Any()              && !y.Except(x).Any();      }  }  

Answer by TDG for Compare two List objects for equality, ignoring order


I use this method )

public delegate bool CompareValue(T1 val1, T2 val2);    public static bool CompareTwoArrays(this IEnumerable array1, IEnumerable array2, CompareValue compareValue)  {      return array1.Select(item1 => array2.Any(item2 => compareValue(item1, item2))).All(search => search)              && array2.Select(item2 => array1.Any(item1 => compareValue(item1, item2))).All(search => search);  }  

Answer by Suhail for Compare two List objects for equality, ignoring order


This worked for me:
If you are comparing two lists of objects depend upon single entity like ID, and you want a third list which matches that condition, then you can do the following:

list3=List1.Where(n => !List2.select(n1 => n1.Id).Contains.(n.Id));  

Refer: MSDN - C# Compare Two lists of objects


Fatal error: Call to a member function getElementsByTagName() on a non-object in D:\XAMPP INSTALLASTION\xampp\htdocs\endunpratama9i\www-stackoverflow-info-proses.php on line 72

0 comments:

Post a Comment

Popular Posts

Powered by Blogger.