Comparing Arrays using LINQ in C#
I've two arrays like
string[] a = { "a", "b", "c" };
string[] b = { "a", "b", "c" };开发者_开发知识库
I need to compare the two arrays using LINQ.
The comparison should take place only if both arrays have same size. The data can be in any order and still return true if all values of a[] and all values of b[] are the same.
string[] a = { "a", "b" };
string[] b = { "a", "b" };
return (a.Length == b.Length && a.Intersect(b).Count() == a.Length);
After some performance testing:
- Over 10,000 small strings - 5ms
- Over 100,000 small strings - 99ms
- Over 1,000,000 small strings - Avg. 601ms
- Over 100,000 ~500 character strings - 190ms
Not sure about the performance, but this seems to work.
string[] a = { "a", "b", "c" };
string[] b = { "a", "b", "c" };
bool result = a.SequenceEqual(b);
Assert.AreEqual(true, result);
However, it is not order independent so it does not fulfill the OP's requirement.
string[] a = { "a", "b", "c" };
string[] b = { "a", "c", "b" };
bool result = a.SequenceEqual(b);
Assert.AreEqual(false, result);
I think this will always be an O(n log n) operation, so I'd just sort both arrays and compare them e.g. using SequenceEqual.
if order doesn't matter or there can be duplicates, then perhaps:
public static class IEnumerableExtensions
{
public static bool HasSameContentsAs<T>(this ICollection<T> source,
ICollection<T> other)
{
if (source.Count != other.Count)
{
return false;
}
var s = source
.GroupBy(x => x)
.ToDictionary(x => x.Key, x => x.Count());
var o = other
.GroupBy(x => x)
.ToDictionary(x => x.Key, x => x.Count());
int count;
return s.Count == o.Count &&
s.All(x => o.TryGetValue(x.Key, out count) &&
count == x.Value);
}
}
usage:
string[] a = { "a", "b", "c" };
string[] b = { "c", "a", "b" };
bool containSame = a.HasSameContentsAs(b);
some use cases:
different lengths (expect false)
string[] a = { "a", "b", "c" }; string[] b = { "b", "c" };
different order (expect true)
string[] a = { "a", "b", "c" }; string[] b = { "b", "c", "a" };
also works if the inputs can contain duplicate items, though it isn't clear from the question whether that characteristic is desired or not, consider:
duplicated items have same count (expect true)
string[] a = { "a", "b", "b", "c" }; string[] b = { "a", "b", "c", "b" };
duplicated items with different counts (expect false)
string[] a = { "a", "b", "b", "b", "c" }; string[] b = { "a", "b", "c", "b", "c" };
This works correctly with duplicates and check each element
a.Length == b.Length && !a.Where((t, i) => t != b[i]).Any()
IDictionary<int, object> a = new Dictionary<int, object>();
IDictionary<int, object> b = new Dictionary<int, object>();
a.Add(1, "1");
a.Add(2, 2);
a.Add(3, "3");
b.Add(3, "3");
b.Add(1, "1");
b.Add(2, 2);
Console.WriteLine(a.All(i => b.Contains(i)) && b.All(i => a.Contains(i)));
精彩评论