Andrew Florko
Andrew Florko

Reputation: 7750

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 is in A (A items and B items may have different order).

Upvotes: 6

Views: 4892

Answers (6)

LukeH
LukeH

Reputation: 269498

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.)

Upvotes: 0

Tom
Tom

Reputation: 3374

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;
}

Upvotes: 0

Tomas Jansson
Tomas Jansson

Reputation: 23472

var result = A.Count == B.Count && A.Where(y => B.Contains(y)).Count() == A.Count;

Maybe?

Upvotes: 0

Andy
Andy

Reputation: 30418

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.

Upvotes: 1

Ani
Ani

Reputation: 113442

A.Count == B.Count && new HashSet<string>(A).SetEquals(B);

If different frequencies of duplicates are an issue, check out this question.

Upvotes: 2

Jon Skeet
Jon Skeet

Reputation: 1502166

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 :)

Upvotes: 25

Related Questions