|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
|
|
|
|
|
namespace ZeroLevel
|
|
|
|
|
{
|
|
|
|
|
public static partial class CollectionComparsionExtensions
|
|
|
|
|
{
|
|
|
|
|
private sealed class SimpleComparer<T> : IEqualityComparer<T>
|
|
|
|
|
{
|
|
|
|
|
private readonly Func<T, T, bool> _comparer;
|
|
|
|
|
|
|
|
|
|
public SimpleComparer()
|
|
|
|
|
{
|
|
|
|
|
_comparer = (a, b) => object.Equals(a, b);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public SimpleComparer(Func<T, T, bool> comparer)
|
|
|
|
|
{
|
|
|
|
|
_comparer = comparer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool Equals(T x, T y)
|
|
|
|
|
{
|
|
|
|
|
return _comparer(x, y);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int GetHashCode(T obj)
|
|
|
|
|
{
|
|
|
|
|
return obj.GetHashCode();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Checks for the same content of a collection of strings, including sorted in different ways
|
|
|
|
|
/// </summary>
|
|
|
|
|
public static bool StringEnumerableEquals(this IEnumerable<string> A, IEnumerable<string> B)
|
|
|
|
|
{
|
|
|
|
|
if (A == null && B == null) return true;
|
|
|
|
|
if (A == null || B == null) return false;
|
|
|
|
|
return A.Count() == B.Count() && A.Intersect(B).Count() == B.Count();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Checks for the same content of collections, including sorted in different ways
|
|
|
|
|
/// </summary>
|
|
|
|
|
public static bool NoOrderingEquals<T>(this IEnumerable<T> A, IEnumerable<T> B)
|
|
|
|
|
{
|
|
|
|
|
if (A == null && B == null) return true;
|
|
|
|
|
if (A == null || B == null) return false;
|
|
|
|
|
return A.Count() == B.Count() && A.Intersect(B, new SimpleComparer<T>()).Count() == B.Count();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static bool NoOrderingEquals<T>(this IEnumerable<T> A, IEnumerable<T> B, Func<T, T, bool> comparer)
|
|
|
|
|
{
|
|
|
|
|
if (A == null && B == null) return true;
|
|
|
|
|
if (A == null || B == null) return false;
|
|
|
|
|
return A.Count() == B.Count() && A.Intersect(B, new SimpleComparer<T>(comparer)).Count() == B.Count();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Checks for the same content collections
|
|
|
|
|
/// </summary>
|
|
|
|
|
public static bool OrderingEquals<T>(this IEnumerable<T> A, IEnumerable<T> B)
|
|
|
|
|
{
|
|
|
|
|
if (A == null && B == null) return true;
|
|
|
|
|
if (A == null || B == null) return false;
|
|
|
|
|
if (A.Count() != B.Count()) return false;
|
|
|
|
|
var enumA = A.GetEnumerator();
|
|
|
|
|
var enumB = B.GetEnumerator();
|
|
|
|
|
while (enumA.MoveNext() && enumB.MoveNext())
|
|
|
|
|
{
|
|
|
|
|
if (enumA.Current == null && enumB.Current == null) continue;
|
|
|
|
|
if (enumA.Current == null || enumB.Current == null) return false;
|
|
|
|
|
if (enumA.Current.Equals(enumB.Current) == false) return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static bool OrderingEquals<T>(this IEnumerable<T> A, IEnumerable<T> B, Func<T, T, bool> comparer)
|
|
|
|
|
{
|
|
|
|
|
if (A == null && B == null) return true;
|
|
|
|
|
if (A == null || B == null) return false;
|
|
|
|
|
if (A.Count() != B.Count()) return false;
|
|
|
|
|
var enumA = A.GetEnumerator();
|
|
|
|
|
var enumB = B.GetEnumerator();
|
|
|
|
|
while (enumA.MoveNext() && enumB.MoveNext())
|
|
|
|
|
{
|
|
|
|
|
if (enumA.Current == null && enumB.Current == null) continue;
|
|
|
|
|
if (enumA.Current == null || enumB.Current == null) return false;
|
|
|
|
|
if (comparer(enumA.Current, enumB.Current) == false) return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Calculate hash for collection
|
|
|
|
|
/// </summary>
|
|
|
|
|
public static int GetEnumHashCode<T>(this IEnumerable<T> A)
|
|
|
|
|
{
|
|
|
|
|
int hc = 0;
|
|
|
|
|
if (A != null)
|
|
|
|
|
{
|
|
|
|
|
foreach (var p in A)
|
|
|
|
|
hc ^= p.GetHashCode();
|
|
|
|
|
}
|
|
|
|
|
return hc;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|