Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

pytest comparing two lists containing dictionaries, by content [duplicate]

I'm looking for an easy (and quick) way to determine if two unordered lists contain the same elements:

For example:

['one', 'two', 'three'] == ['one', 'two', 'three'] :  true
['one', 'two', 'three'] == ['one', 'three', 'two'] :  true
['one', 'two', 'three'] == ['one', 'two', 'three', 'three'] :  false
['one', 'two', 'three'] == ['one', 'two', 'three', 'four'] :  false
['one', 'two', 'three'] == ['one', 'two', 'four'] :  false
['one', 'two', 'three'] == ['one'] :  false

I'm hoping to do this without using a map.

like image 851
Paul Avatar asked Mar 08 '12 18:03

Paul


People also ask

How do you compare two dictionaries with the same key in Python?

To compare two dictionaries and checking how many (key, value) pairs are equal with Python, we can use dict comprehension. to get the values in dict x if they're key k is in dict y and x[k] is equal to y[k] . And then we check the length of the shared_items dict to see which items are the same in both dicts x and y .

Can two dictionaries be compared?

When I had to compare two dictionaries for the first time, I struggled―a lot! For simple dictionaries, comparing them is usually straightforward. You can use the == operator, and it will work.

How do I check if two dictionaries are equal in Python?

The simplest technique to check if two or multiple dictionaries are equal is by using the == operator in Python. You can create the dictionaries with any of the methods defined in Python and then compare them using the == operator. It will return True the dictionaries are equals and False if not.


4 Answers

Python has a built-in datatype for an unordered collection of (hashable) things, called a set. If you convert both lists to sets, the comparison will be unordered.

set(x) == set(y)

Documentation on set


EDIT: @mdwhatcott points out that you want to check for duplicates. set ignores these, so you need a similar data structure that also keeps track of the number of items in each list. This is called a multiset; the best approximation in the standard library is a collections.Counter:

>>> import collections
>>> compare = lambda x, y: collections.Counter(x) == collections.Counter(y)
>>> 
>>> compare([1,2,3], [1,2,3,3])
False
>>> compare([1,2,3], [1,2,3])
True
>>> compare([1,2,3,3], [1,2,2,3])
False
>>> 
like image 96
Katriel Avatar answered Sep 24 '22 18:09

Katriel


If elements are always nearly sorted as in your example then builtin .sort() (timsort) should be fast:

>>> a = [1,1,2]
>>> b = [1,2,2]
>>> a.sort()
>>> b.sort()
>>> a == b
False

If you don't want to sort inplace you could use sorted().

In practice it might always be faster then collections.Counter() (despite asymptotically O(n) time being better then O(n*log(n)) for .sort()). Measure it; If it is important.

like image 20
jfs Avatar answered Sep 20 '22 18:09

jfs


sorted(x) == sorted(y)

Copying from here: Check if two unordered lists are equal

I think this is the best answer for this question because

  1. It is better than using counter as pointed in this answer
  2. x.sort() sorts x, which is a side effect. sorted(x) returns a new list.
like image 27
Md Enzam Hossain Avatar answered Sep 23 '22 18:09

Md Enzam Hossain


You want to see if they contain the same elements, but don't care about the order.

You can use a set:

>>> set(['one', 'two', 'three']) == set(['two', 'one', 'three'])
True

But the set object itself will only contain one instance of each unique value, and will not preserve order.

>>> set(['one', 'one', 'one']) == set(['one'])
True

So, if tracking duplicates/length is important, you probably want to also check the length:

def are_eq(a, b):
    return set(a) == set(b) and len(a) == len(b)
like image 42
Matimus Avatar answered Sep 21 '22 18:09

Matimus