2016-11-24 109 views
2

我在Python中有一个包含“嵌套”字典的列表。所以我的列表如下所示:在python的字典列表中获取某个键的所有值

List = [{'entry' : {'Name' : 'Smith', 'Age' : 25}}, {'entry' : {'Name' : 'Mary', 'Age' : 28}}] 

我想从列表中返回所有的密钥'名称'的值,而不使用循环。因此,如果我使用循环它可以工作,因为这对列表的单个条目起作用。例如:List[0]['entry']['Name']作品并返回'Smith'。然而,我需要像List[:]['entry']['Name']这应该返回一个列表中的条目'史密斯'和'玛丽'在其中。这可能吗?

+0

你说你不想为了性能的原因使用for-loop或list的理解,因为你的数据有“数以百万计”的条目。几百万 - 1,10,100?如果答案是100万,那么我的基本台式机上的迭代大约需要0.13秒。如果你的答案是1000万或1亿,我建议你完全需要一个不同的策略 - 一个是数据不一定保存在内存中,另一个是存储数据的方式,以便你的主要查询可以快速得到回答。 – FMc

回答

1

我已经张贴reduce()方法的好奇心,但由于答案被接受,我张贴的timeit结果,比较此票上其他答案的表现。

from timeit import timeit 
import functools 

def _reduce_py2(the_list): 

    return reduce(lambda l, src: l.append(src['entry']['Name']) or l, the_list, []) 

def _reduce_py3(the_list): 

    return functools.reduce(lambda l, src: l.append(src['entry']['Name']) or l, the_list, []) 

def _map_py2(the_list): 

    return map(lambda d: d['entry']['Name'], the_list) 

def _map_py3(the_list): 

    return [i for i in map(lambda d: d['entry']['Name'], the_list)] 

def _list(the_list): 

    return [d['entry']['Name'] for d in the_list] 

the_list = [] 
for i in range(1000): 
    the_list += [{'entry' : {'Name' : 'Smith%s' % i, 'Age' : i}}] 


reps = 1000 

# Compare timings 

print('Reduce:    ', timeit('c(the_list)', 'from __main__ import _reduce_py2 as c, the_list', number=reps)) 
print('Map:     ', timeit('c(the_list)', 'from __main__ import _map_py2 as c, the_list', number=reps)) 
print('List comprehension: ', timeit('c(the_list)', 'from __main__ import _list as c, the_list', number=reps)) 

结果:

Py 2 
Reduce:    0.2090609073638916 
Map:     0.136185884475708 
List comprehension: 0.07403087615966797 

Py 3 
Reduce:    0.20160907896934077 
Map:     0.17127344600157812 
List comprehension: 0.06799810699885711 

结论,list comprehension是最快的方法。不过,python 3上的map返回了一个生成器。

2

您可以使用:

[o['entry']['Name'] for o in List] 

结果:[ '史密斯', '玛丽']

注意,它仍然是循环。没有循环,你不能做这样的事情。

4

您可以使用lambda expressionmap()为:

>>> map(lambda d: d['entry']['Name'], List) 
['Smith', 'Mary'] 

即使你没有看到循环在这里,但在内部map()还遍历列表。你不能跳过迭代列表来实现你想要的。

更好的办法,是用列表理解为:

>>> [d['entry']['Name'] for d in List] 
['Smith', 'Mary'] 

,或者,如果有任何关键嵌套字典丢失的可能性,您可以添加过滤器:

>>> [d['entry']['Name'] for d in List if 'entry' in d and 'Name' in d['entry']] 
['Smith', 'Mary'] 
2

不幸的是,这在python中是不可能的,尽管这将是一个非常有用的功能。类似的功能通常只在特定于域的查询语言中可用(例如,我认为Django ORM支持类似的索引),但不能用我能想到的任何通用语言。

你最好的办法是

[item['Entry']['Name'] for item in List] 
2

我不知道为什么你不能使用循环,但会列表理解的工作?让我知道原因,也许我可以推荐别的东西。

a = [{'entry' : {'Name' : 'Smith', 'Age' : 25}}, {'entry' : {'Name' : 'Mary', 'Age' : 28}}] 
b = [a[i]['entry']['Name'] for i in range(len(a))] 

结果: B = [ '史密斯', '玛丽']

+1

由于性能方面的原因,我不想使用循环(为了保持更快),因为我的实际列表包含数百万条目。 – mshabeeb

相关问题