0

I have come across this case a few times now: I have an array which contains an element I want and I want to select that element without knowing the index, and instead knowing some desired property (maybe it is a list of dictionaries and I want the dictionary elem such that elem['foo'] == 'bar').

A solution I have is do a filter (or more pythonically, a list comprehension) and then take the first element (often times I know that the filtered list will be a singleton, so taking the first is taking the only).

Ex. Given a list x = [{'foo': 'bar_1'}, {'foo': 'bar_2'}], I want the element whose 'foo' value is 'bar2'. So I do this :

y = [elem for elem in x if elem['foo'] == 'bar_2'][0]

Is there a more standard way of doing this? It seems like a very simple and common use case.

1

2 Answers 2

1

If you run into this problem frequently then consider using a different data structure. Think about whether a list of dicts is really the best data structure for the problem you are solving. Or, if it is, add a dict to keep track of the information you require. In this case, as you build x, also build index:

index = {'bar2':x[1], 'bar1':x[0]}

Dict lookups are O(1), whereas any list-based lookup is O(n).

Sign up to request clarification or add additional context in comments.

Comments

1

You can use a generator calling next on it to get the first match:

l = [{'foo': 'bar_1'}, {'foo': 'bar_2'}]
print next(d for d in l if d["foo"] == "bar_2")
{'foo': 'bar_2'}

d = (d for d in l if d["foo"] == "bar_2")
first = next(d)

You could also you itertools.dropwhile and if you want the first two elements:

In [52]: from itertools import dropwhile,takewhile
In [53]: l = [{'foo': 'bar_1'}, {'foo': 'bar_2'},{'foo': 'bar_2',"goo":"bar"}]
In [54]: d = dropwhile(lambda x: x["foo"] != "bar_2",l)   # drop elements whose where value of key "foo" is not equal to "bar_2"
In [55]: first = next(d)
In [56]: second = next(d)    
In [57]: first
Out[57]: {'foo': 'bar_2'}    
In [58]: second
Out[58]: {'foo': 'bar_2', 'goo': 'bar'}

2 Comments

Alternatively, item, = (d for d in l if d["foo"] == "bar_2") will assert that there is only one item in the list with the given property (which may, or may not be desired).
@Dunes, yes true, I am not sure if the OP wants to check if there is only one match or just get the first.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.