a = [1, 2, 3, 1, 2, 3]
b = [3, 2, 1, 3, 2, 1]
a & b should be considered equal, because they have exactly the same elements, only in different order.
The thing is, my actual lists will consist of objects (my class instances), not integers.
a = [1, 2, 3, 1, 2, 3]
b = [3, 2, 1, 3, 2, 1]
a & b should be considered equal, because they have exactly the same elements, only in different order.
The thing is, my actual lists will consist of objects (my class instances), not integers.
If you know the items are always hashable, you can use a
Counter()
which is O(n)If you know the items are always sortable, you can use
sorted()
which is O(n log n)In the general case you can't rely on being able to sort, or has the elements, so you need a fallback like this, which is unfortunately O(n^2)
https://docs.python.org/3.5/library/unittest.html#unittest.TestCase.assertCountEqual
assertCountEqual(first, second, msg=None)
Test that sequence first contains the same elements as second, regardless of their order. When they don’t, an error message listing the differences between the sequences will be generated.
Duplicate elements are not ignored when comparing first and second. It verifies whether each element has the same count in both sequences. Equivalent to: assertEqual(Counter(list(first)), Counter(list(second))) but works with sequences of unhashable objects as well.
New in version 3.2.
or in 2.7: https://docs.python.org/2.7/library/unittest.html#unittest.TestCase.assertItemsEqual
You can sort both:
A counting sort could also be more efficient (but it requires the object to be hashable).
The best way to do this is by sorting the lists and comparing them. (Using
Counter
won't work with objects that aren't hashable.) This is straightforward for integers:It gets a little trickier with arbitrary objects. If you care about object identity, i.e., whether the same objects are in both lists, you can use the
id()
function as the sort key.(In Python 2.x you don't actually need the
key=
parameter, because you can compare any object to any object. The ordering is arbitrary but stable, so it works fine for this purpose; it doesn't matter what order the objects are in, only that the ordering is the same for both lists. In Python 3, though, comparing objects of different types is disallowed in many circumstances -- for example, you can't compare strings to integers -- so if you will have objects of various types, best to explicitly use the object's ID.)If you want to compare the objects in the list by value, on the other hand, first you need to define what "value" means for the objects. Then you will need some way to provide that as a key (and for Python 3, as a consistent type). One potential way that would work for a lot of arbitrary objects is to sort by their
repr()
. Of course, this could waste a lot of extra time and memory buildingrepr()
strings for large lists and so on.If the objects are all your own types, you can define
__lt__()
on them so that the object knows how to compare itself to others. Then you can just sort them and not worry about thekey=
parameter. Of course you could also define__hash__()
and useCounter
, which will be faster.O(n): The Counter() method is best (if your objects are hashable):
O(n log n): The sorted() method is next best (if your objects are orderable):
O(n * n): If the objects are neither hashable, nor orderable, you can use equality:
If the comparison is to be performed in a testing context, use
assertCountEqual(a, b)
(py>=3.2
) andassertItemsEqual(a, b)
(2.7<=py<3.2
).Works on sequences of unhashable objects too.