code_junkie

Comparing two collections for equality

Nov 10th, 2011
120
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.10 KB | None | 0 0
  1. collection1 = {1, 2, 3, 4};
  2. collection2 = {2, 4, 1, 3};
  3.  
  4. collection1 == collection2; // true
  5.  
  6. if (collection1.Count != collection2.Count)
  7. return false; // the collections are not equal
  8.  
  9. foreach (Item item in collection1)
  10. {
  11. if (!collection2.Contains(item))
  12. return false; // the collections are not equal
  13. }
  14.  
  15. foreach (Item item in collection2)
  16. {
  17. if (!collection1.Contains(item))
  18. return false; // the collections are not equal
  19. }
  20.  
  21. return true; // the collections are equal
  22.  
  23. collection1 = {1, 2, 3, 3, 4}
  24. collection2 = {1, 2, 2, 3, 4}
  25.  
  26. public class CollectionComparer<T> : IEqualityComparer<IEnumerable<T>>
  27. {
  28. public bool Equals(IEnumerable<T> first, IEnumerable<T> second)
  29. {
  30. if ((first == null) != (second == null))
  31. return false;
  32.  
  33. if (!object.ReferenceEquals(first, second) && (first != null))
  34. {
  35. if (first.Count() != second.Count())
  36. return false;
  37.  
  38. if ((first.Count() != 0) && HaveMismatchedElement(first, second))
  39. return false;
  40. }
  41.  
  42. return true;
  43. }
  44.  
  45. private static bool HaveMismatchedElement(IEnumerable<T> first,
  46. IEnumerable<T> second)
  47. {
  48. int firstCount;
  49. int secondCount;
  50.  
  51. var firstElementCounts = GetElementCounts(first, out firstCount);
  52. var secondElementCounts = GetElementCounts(second, out secondCount);
  53.  
  54. if (firstCount != secondCount)
  55. return true;
  56.  
  57. foreach (var kvp in firstElementCounts)
  58. {
  59. firstCount = kvp.Value;
  60. secondElementCounts.TryGetValue(kvp.Key, out secondCount);
  61.  
  62. if (firstCount != secondCount)
  63. return true;
  64. }
  65.  
  66. return false;
  67. }
  68.  
  69. private static Dictionary<T, int> GetElementCounts(IEnumerable<T> enumerable,
  70. out int nullCount)
  71. {
  72. var dictionary = new Dictionary<T, int>();
  73. nullCount = 0;
  74.  
  75. foreach (T element in enumerable)
  76. {
  77. if (element == null)
  78. {
  79. nullCount++;
  80. }
  81. else
  82. {
  83. int num;
  84. dictionary.TryGetValue(element, out num);
  85. num++;
  86. dictionary[element] = num;
  87. }
  88. }
  89.  
  90. return dictionary;
  91. }
  92.  
  93. public int GetHashCode(IEnumerable<T> enumerable)
  94. {
  95. int hash = 17;
  96.  
  97. foreach (T val in enumerable.OrderBy(x => x))
  98. hash = hash * 23 + val.GetHashCode();
  99.  
  100. return hash;
  101. }
  102. }
  103.  
  104. private bool SetEqual (List<int> left, List<int> right) {
  105.  
  106. if (left.Count != right.Count)
  107. return false;
  108.  
  109. Dictionary<int, int> dict = new Dictionary<int, int>();
  110.  
  111. foreach (int member in left) {
  112. if (dict.ContainsKey(member) == false)
  113. dict[member] = 1;
  114. else
  115. dict[member]++;
  116. }
  117.  
  118. foreach (int member in right) {
  119. if (dict.ContainsKey(member) == false)
  120. return false;
  121. else
  122. dict[member]--;
  123. }
  124.  
  125. foreach (KeyValuePair<int, int> kvp in dict) {
  126. if (kvp.Value != 0)
  127. return false;
  128. }
  129.  
  130. return true;
  131.  
  132. }
  133.  
  134. /// <summary>
  135. /// Represents a service used to compare two collections for equality.
  136. /// </summary>
  137. /// <typeparam name="T">The type of the items in the collections.</typeparam>
  138. public class CollectionComparer<T>
  139. {
  140. /// <summary>
  141. /// Compares the content of two collections for equality.
  142. /// </summary>
  143. /// <param name="foo">The first collection.</param>
  144. /// <param name="bar">The second collection.</param>
  145. /// <returns>True if both collections have the same content, false otherwise.</returns>
  146. public bool Execute(ICollection<T> foo, ICollection<T> bar)
  147. {
  148. // Declare a dictionary to count the occurence of the items in the collection
  149. Dictionary<T, int> itemCounts = new Dictionary<T,int>();
  150.  
  151. // Increase the count for each occurence of the item in the first collection
  152. foreach (T item in foo)
  153. {
  154. if (itemCounts.ContainsKey(item))
  155. {
  156. itemCounts[item]++;
  157. }
  158. else
  159. {
  160. itemCounts[item] = 1;
  161. }
  162. }
  163.  
  164. // Wrap the keys in a searchable list
  165. List<T> keys = new List<T>(itemCounts.Keys);
  166.  
  167. // Decrease the count for each occurence of the item in the second collection
  168. foreach (T item in bar)
  169. {
  170. // Try to find a key for the item
  171. // The keys of a dictionary are compared by reference, so we have to
  172. // find the original key that is equivalent to the "item"
  173. // You may want to override ".Equals" to define what it means for
  174. // two "T" objects to be equal
  175. T key = keys.Find(
  176. delegate(T listKey)
  177. {
  178. return listKey.Equals(item);
  179. });
  180.  
  181. // Check if a key was found
  182. if(key != null)
  183. {
  184. itemCounts[key]--;
  185. }
  186. else
  187. {
  188. // There was no occurence of this item in the first collection, thus the collections are not equal
  189. return false;
  190. }
  191. }
  192.  
  193. // The count of each item should be 0 if the contents of the collections are equal
  194. foreach (int value in itemCounts.Values)
  195. {
  196. if (value != 0)
  197. {
  198. return false;
  199. }
  200. }
  201.  
  202. // The collections are equal
  203. return true;
  204. }
  205. }
  206.  
  207. bool equal = collection1.OrderBy(i => i).SequenceEqual(
  208. collection2.OrderBy(i => i);
  209.  
  210. return c1.Count == c2.Count && c1.Intersect(c2).Count() == c1.Count;
  211.  
  212. __Test Latency(ms)__
  213. N, SetEquals, OrderBy, Intersect
  214. 1024, 0, 0, 0
  215. 2048, 0, 0, 0
  216. 4096, 31.2468, 0, 0
  217. 8192, 62.4936, 0, 0
  218. 16384, 156.234, 15.6234, 0
  219. 32768, 312.468, 15.6234, 46.8702
  220. 65536, 640.5594, 46.8702, 31.2468
  221. 131072, 1312.3656, 93.7404, 203.1042
  222. 262144, 3765.2394, 187.4808, 187.4808
  223. 524288, 5718.1644, 374.9616, 406.2084
  224. 1048576, 11420.7054, 734.2998, 718.6764
  225. 2097152, 35090.1564, 1515.4698, 1484.223
  226.  
  227. (new HashBag(collection1)).equals(new HashBag(collection2))
  228.  
  229. // Create the IEnumerable data sources.
  230. string[] names1 = System.IO.File.ReadAllLines(@"../../../names1.txt");
  231. string[] names2 = System.IO.File.ReadAllLines(@"../../../names2.txt");
  232. // Create the query. Note that method syntax must be used here.
  233. IEnumerable<string> differenceQuery = names1.Except(names2);
  234. // Execute the query.
  235. Console.WriteLine("The following lines are in names1.txt but not names2.txt");
  236. foreach (string s in differenceQuery)
  237. Console.WriteLine(s);
  238.  
  239. [Serializable]
  240. public class SetComparer<T> : IEqualityComparer<IEnumerable<T>>
  241. where T:IComparable<T>
  242. {
  243. public bool Equals(IEnumerable<T> first, IEnumerable<T> second)
  244. {
  245. if (first == second)
  246. return true;
  247. if ((first == null) || (second == null))
  248. return false;
  249. return first.ToHashSet().SetEquals(second);
  250. }
  251.  
  252. public int GetHashCode(IEnumerable<T> enumerable)
  253. {
  254. int hash = 17;
  255.  
  256. foreach (T val in enumerable.OrderBy(x => x))
  257. hash = hash * 23 + val.GetHashCode();
  258.  
  259. return hash;
  260. }
  261. }
  262.  
  263. var list1 = new[] { "Bill", "Bob", "Sally" };
  264. var list2 = new[] { "Bob", "Bill", "Sally" };
  265. bool isequal = list1.Compare(list2).IsSame;
  266.  
  267. var list1 = new[] { "Billy", "Bob" };
  268. var list2 = new[] { "Bob", "Sally" };
  269. var diff = list1.Compare(list2);
  270. var onlyinlist1 = diff.Removed; //Billy
  271. var onlyinlist2 = diff.Added; //Sally
  272. var inbothlists = diff.Equal; //Bob
  273.  
  274. var original = new Dictionary<int, string>() { { 1, "a" }, { 2, "b" } };
  275. var changed = new Dictionary<int, string>() { { 1, "aaa" }, { 2, "b" } };
  276. var diff = original.Compare(changed, (x, y) => x.Value == y.Value, (x, y) => x.Value == y.Value);
  277. foreach (var item in diff.Different)
  278. Console.Write("{0} changed to {1}", item.Key.Value, item.Value.Value);
  279. //Will output: a changed to aaa
Add Comment
Please, Sign In to add comment