2016-11-24 111 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

相關問題