简体   繁体   中英

Python: Best way to check that all specific keys in a list of dictionaries all contain a specific value for another key

I have a list of dictionaries. As an example, it looks like this:

[{'cond_name': 'Cond1', 'rand': 'idk', 'medical': 'any'},{'cond_name': 'Cond2', 'rand': 'idk', 'medical': 'any'},{'cond_name': 'Cond1', 'rand': 'different', 'medical': 'something'},{'cond_name': 'Cond1', 'rand': 'mine', 'medical': 'any'}]

What I want to do is write a function which takes the list of dictionaries as input and verifies that every time the key 'cond_name' has value 'Cond1', that it also has the 'medical' key value of 'any'.

In this example, you can see immediately that the 1st and 4th dictionary in this example list are okay because they both have cond_name of Cond1 and both have 'medical' value of 'any'. But this would not pass overall because the 3rd dictionary value has 'cond_name' of 'Cond1' and 'medical' value of 'something' which doesn't match with the others. So this would return a False value from the function since they all don't match. Notice that the second key-value pair with 'rand' doesn't affect the results.

I could hack together a way to solve this, but wondering if there is any very efficient or neat ways to handle this since it seems like a problem that could be frequent. Thanks.

I did a little benchmark comparing all() and plain for-loop (as you stated you want efficient way to handle the problem):

from timeit import timeit


d = [
    {"cond_name": "Cond1", "rand": "idk", "medical": "any"},
    {"cond_name": "Cond2", "rand": "idk", "medical": "any"},
    {"cond_name": "Cond1", "rand": "different", "medical": "something"},
    {"cond_name": "Cond1", "rand": "mine", "medical": "any"},
]


def fn1():
    return all(i["medical"] == "any" for i in d if i["cond_name"] == "Cond1")


def fn2():
    return all(i["cond_name"] != "Cond1" or i["medical"] == "any" for i in d)


def fn3():
    for i in d:
        if i["cond_name"] == "Cond1" and i["medical"] != "any":
            return False
    return True


assert fn1() == fn2() == fn3()

t1 = timeit(fn1, number=1_000_000)
t2 = timeit(fn2, number=1_000_000)
t3 = timeit(fn3, number=1_000_000)

print(t1)
print(t2)
print(t3)

Prints on my machine (Python 3.9.7/AMD 3700X):

0.6374830791028216
0.6326718209311366
0.2943508509779349

As you see plain for-loop is more efficient. But it depends on your data, if you don't have lots of items I'd use all() as it's more clean and pythonic.

EDIT: Changed the logic of fn2() and fn3()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM