2014-08-28 177 views
0

我已经遇到过这种情况几次了:我有一个数组,其中包含我想要的元素,并且我想在不知道索引的情况下选择该元素,而是知道一些期望的属性(也许这是一个字典列表,我想字典elem,使得elem['foo'] == 'bar')。Python - 从数组中选择一个具有某个属性的元素

我有一个解决方案是做一个过滤器(或更多的pythonically,列表理解),然后采取第一个元素(通常我知道被过滤的列表将是一个单身,所以采取第一个是唯一的) 。

Ex。给定一个列表x = [{'foo': 'bar_1'}, {'foo': 'bar_2'}],我想要的元素的值为'foo'值为'bar2'。所以我这样做:

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

有没有一个更标准的方式做到这一点?这似乎是一个非常简单和常见的用例。

+0

可能重复[ Python:找到匹配谓词的序列中的第一个元素](http://stackoverflow.com/questions/8534256/python-find-first-element-in-a-sequence-that-matches-a-predicate) – 2014-08-28 21:53:50

回答

1

如果您经常遇到此问题,请考虑使用不同的数据结构。想想一下,一张字典是否真的是你正在解决的问题的最佳数据结构。或者,如果是,请添加dict以跟踪您所需的信息。在这种情况下,为您打造x,还建立index

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

Dict lookups are O(1),而任何基于列表的查找是O(n)

+1

@ carl.anderson:不,它是O(1)。查看https://wiki.python.org/moin/TimeComplexity – 2014-08-28 20:24:16

1

可以使用generator呼吁它next拿到第一场比赛:

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) 

你也可以你itertools.dropwhile,如果你想前两个要素:

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'} 
+0

或者,'item,=(d for d in l if if [[foo]] ==“bar_2”)'将声明只有一个项目在具有给定属性的列表(可能或可能不需要)。 – Dunes 2014-08-28 20:28:01

+0

另一个随机downvote – 2014-08-28 20:33:10

+0

@Dunes,是的真的,我不确定OP是否想要检查是否只有一个匹配或只是得到第一个。 – 2014-08-28 20:34:19

相关问题