0

I'd like to efficiently compare two lists and determine if both share exactly the same elements.

The lists can be None, empty and of various lengths. Ordering of the elements inside the list does not matter, so ['a', 'b', 'c'] == ['a', 'c', 'b'] are equal in my case.

My current solution looks like this:

 def list_a_equals_list_b(list_a, list_b):
    if list_a != None and list_b != None:
        if len(list_a) != len(list_b):
            return False
        else:
            return len(frozenset(list_a).intersection(list_b)) == len(list_a)
    elif list_a == None and list_b == None:
        return True
    else:
        return False

Is there a more efficient way to compare those lists?

Thanks!

2
  • 2
    Can you have repeated elements in your lists? Commented Mar 11, 2020 at 18:37
  • You got me here ;-). Didn't think about duplicates yet, as in my current use case I can exclude them. Obviously the code from above, won't work with those. So at the moment: no duplicates :-) Commented Mar 11, 2020 at 18:48

2 Answers 2

2

If you don't have duplicates in either lists you can use a set:

if listA == listB  \
or listA and listB \
   and len(listA) == len(listB) \
   and not set(listA).symmetric_difference(listB):
   # lists have the same elements
else:
   # there are differences

If you do allow duplicates, then yo can use Counter from collections (which would also work if you don't have duplicates)

from collections import Counter

if listA == listB  \
or listA and listB \
   and len(listA) == len(listB) \
   and Counter(listA)==Counter(listB):
   # lists have the same elements
else:
   # there are differences
Sign up to request clarification or add additional context in comments.

3 Comments

symmetric_difference was the function I was looking for, Thx! For sure I'll keep the length comparision. The issue was the 'frozenset(list_a).intersection(list_b)' part :-)
Using the symmetric_difference method unnecessarily creates a new set just so you can test if it's empty, resulting in more overhead. Simply doing set(list_a) == set(list_b) would be enough.
With both list being the same length, symetric_difference will be more efficient because it does not require creation of a set for listB and will never create a resulting set that is larger than set(listB) even when both lists are completely different. So, from a set creation perspective its worst case scenario is equivalent to creating set(listB) and all other cases will be more efficient
1

The Counter() method is best if your objects are hashable. but here sorted() built-in function is your best option.

def list_a_equals_list_b(list_a, list_b):
    return (list_a == None and list_b == None) or sorted(list_a) == sorted(list_b)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.