开发者

Python: Check if any list element is a key in a dictionary

Given the following code

all_options = { "1": "/test/1", "2": "/test/2", "3": "/test/3" }
s开发者_Go百科elected_options = [ "1", "3" ]

How do I get the entries from all_options where the key matches an entry in selected_options?

I started down the path of using a List Comprehension, but I'm stuck on the last clause:

final = ()
[ final.append(option) for option in all_options if ... ]

Thank you


Just like this?

>>> dict((option, all_options[option]) for option in selected_options if option in all_options)
{'1': '/test/1', '3': '/test/3'}

From Python 2.7 and 3 onwards, you can use the dict comprehension syntax:

{option : all_options[option] for option in selected_options if option in all_options}

Or if you just want the values:

>>> [all_options[option] for option in selected_options if option in all_options]
['/test/1', '/test/3']


[option for option in all_options if option in selected_options]

You may want to make a set of selected_options and use that instead if there are many.


How do I get the entries from all_options where the key matches an entry in selected_options?

With a comprehension. We have two kinds: list comprehensions and generator comprehensions.

Note that this depends on what you mean by "entries". If you want a dict with the key/value pairs that match, then you'll need a comprehension that creates the key/value pairs, and then use that to create a dict by feeding it to the dict constructor.

There is a special syntax rule that says that if we call something callable (like, say, a class constructor) with just one argument, and that argument is a generator comprehension, then we only need one pair of parentheses (instead of two: one to call the function and another to mark the comprehension as a comprehension). This lets us write very natural-looking things.

On the other hand, if you just want a list of keys, then you can just use a list comprehension. (You could pass a generator comprehension to the list constructor, too.)

I started down the path of using a List Comprehension...

You have the wrong idea, fundamentally, about how they work. You don't use them to perform an action repeatedly; you use them to calculate a result repeatedly. You wouldn't make an append call in the first part of the statement because (a) the comprehension is already building the sequence for you, so there's no reason to create another empty sequence to append to; (b) the append call returns None after doing the appending, so you end up with a list of None values that you subsequently throw away.

A list comprehension creates a value. A generator comprehension also creates a value, but it's a generator (so you have to extract its values to use them).

So, how do we write the code?

A list of keys looks like this: for each key in the dict (iterating over a dict iterates over its keys), we want that key (with no modification), only if the key is in our other list. That is, we want [key for key in all_options if key in selected_options]. And that's exactly how you write it in Python. A language could hardly read any more naturally while still being unambiguous.

A dict of key-value pairs looks like this: for each key-value pair in the key-value pairs of the dict, we want that pair, only if the key is in our other list. We want to make a dict using those key-value pairs, so we wrap the comprehension in the dict constructor. To get key-value pairs from a dict, we iterate over its .items(). So, we want a dict constructed from a key and value, for each key and value in the items of the original dict, where the key is in the other list. And again, that's exactly what we write: dict((key, value) for (key, value) in all_options if key in selected_options).

In more recent versions of Python, we can also use a "dict comprehension", which is basically syntactic sugar so that we can write something that looks more like the list comprehension.


Use set() instead, and take advantage of the intersection operation:

>>> final = set(all_options.keys()) & set(selected_options)
>>> print(final)
{'1', '3'}

The above only returns the keys, but NullUserException notes that the question may want the value as well, using a dict comprehention:

>>> {x: all_options[x] for x in set(all_options.keys()) & set(selected_options)}
{'1': '/test/1', '3': '/test/3'}

For completeness, here's just the value:

>>> [all_options[x] for x in set(all_options.keys()) & set(select_options)]
['/test/1', '/test/3']

The below is wrong. Using set() iterates over both lists, instead of just one.

Using sets is better assuming the options become large. The conditional list comprehensions check every item in one of the containers, but a set intersection takes advantage of Python's excellent hashing. Even the list comprehension here only looks up the desired keys in all_options.


I'm not sure which exact contents you're trying to return, so I'm giving a couple of choices:

if your trying to return: ['1', '3']

[option for option in all_options if option in selected_options]

OR

if you're trying to return: ['/test/1', '/test/3']

[all_options[option] for option in all_options if option in selected_options]
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜