C#: how do you check lists are the same size & same elements?
There are two lists of string
List<string> A;
List<string> B;
What is the shortest code you would suggest to check that A.Count == B.Count and each element of A in B and vise versa: every B开发者_StackOverflow中文版 is in A (A items and B items may have different order).
If you don't need to worry about duplicates:
bool equal = new HashSet<string>(A).SetEquals(B);
If you are concerned about duplicates, that becomes slightly more awkward. This will work, but it's relatively slow:
bool equal = A.OrderBy(x => x).SequenceEquals(B.OrderBy(x => x));
Of course you can make both options more efficient by checking the count first, which is a simple expression. For example:
bool equal = (A.Count == B.Count) && new HashSet<string>(A).SetEquals(B);
... but you asked for the shortest code :)
A.Count == B.Count && new HashSet<string>(A).SetEquals(B);
If different frequencies of duplicates are an issue, check out this question.
If you call Enumerable.Except() on the two lists, that will return an IEnumerable<string>
containing all of the elements that are in one list but not the other. If the count of this is 0, then you know that the two lists are the same.
var result = A.Count == B.Count && A.Where(y => B.Contains(y)).Count() == A.Count;
Maybe?
How about a simple loop?
private bool IsEqualLists(List<string> A, List<string> B)
{
for(int i = 0; i < A.Count; i++)
{
if(i < B.Count - 1) {
return false; }
else
{
if(!String.Equals(A[i], B[i]) {
return false;
}
}
}
return true;
}
If you aren't concerned about duplicates, or you're concerned about duplicates but not overly concerned about performance micro-optimisations, then the various techniques in Jon's answer are definitely the way to go.
If you're concerned about duplicates and performance then something like this extension method should do the trick, although it really doesn't meet your "shortest code" criteria!
bool hasSameElements = A.HasSameElements(B);
// ...
public static bool HasSameElements<T>(this IList<T> a, IList<T> b)
{
if (a == b) return true;
if ((a == null) || (b == null)) return false;
if (a.Count != b.Count) return false;
var dict = new Dictionary<string, int>(a.Count);
foreach (string s in a)
{
int count;
dict.TryGetValue(s, out count);
dict[s] = count + 1;
}
foreach (string s in b)
{
int count;
dict.TryGetValue(s, out count);
if (count < 1) return false;
dict[s] = count - 1;
}
return dict.All(kvp => kvp.Value == 0);
}
(Note that this method will return true
if both sequences are null
. If that's not the desired behaviour then it's easy enough to add in the extra null
checks.)
精彩评论