web-dev-qa-db-ja.com

辞書のリストから値のリストを取得する

このような辞書のリストがあります:

[{'value': 'Apple', 'blah': 2}, 
 {'value': 'banana', 'blah': 3} , 
 {'value': 'cars', 'blah': 4}]

['Apple', 'banana', 'cars']が欲しい

これを行う最良の方法は何ですか?

135
SuperString

すべての辞書にvalueキーがあると仮定すると、書くことができます(リストの名前がlであると仮定)

[d['value'] for d in l]

valueが欠落している可能性がある場合は、使用できます

[d['value'] for d in l if 'value' in d]
247
Ismail Badawi

Map()およびlambda関数を使用してそれを行う別の方法を次に示します。

>>> map(lambda d: d['value'], l)

ここで、lはリストです。このように「最もセクシー」に見えますが、リスト内包表記を使用してそれを行います。

更新:キーの使用として「値」が欠落している可能性がある場合:

>>> map(lambda d: d.get('value', 'default value'), l)

更新:私もラムダの大ファンではありません、私は物事に名前を付けることを好む...これは私がそれを念頭に置いてそれを行う方法です:

>>> import operator
>>> map(operator.itemgetter('value'), l)

さらに進んで、達成したいことを明示的に伝える唯一の関数を作成します。

>>> import operator, functools
>>> get_values = functools.partial(map, operator.itemgetter('value'))
>>> get_values(l)
... [<list of values>]

Python 3では、mapは反復子を返すため、listを使用してリストを返します。 list(map(operator.itemgetter('value'), l))

30
Anler
[x['value'] for x in list_of_dicts]
16
Michał Trybus

このような非常に単純なケースでは、 Ismail Badawi's answer のような理解が間違いなく進むべき方法です。

しかし、物事がより複雑になり、複雑な表現を含む複数節またはネストされた内包表記を書き始める必要がある場合、他の代替案を検討する価値があります。 JSONPath、DPath、KVCなど、ネストされたdict-and-list構造でXPathスタイルの検索を指定するいくつかの異なる(準)標準的な方法があります。そして、それらのためにPyPIに素敵なライブラリがあります。

dpath という名前のライブラリの例を次に示します。これは、少し複雑なものを単純化する方法を示しています。

>>> dd = {
...     'fruits': [{'value': 'Apple', 'blah': 2}, {'value': 'banana', 'blah': 3}],
...     'vehicles': [{'value': 'cars', 'blah':4}]}

>>> {key: [{'value': d['value']} for d in value] for key, value in dd.items()}
{'fruits': [{'value': 'Apple'}, {'value': 'banana'}],
 'vehicles': [{'value': 'cars'}]}

>>> dpath.util.search(dd, '*/*/value')
{'fruits': [{'value': 'Apple'}, {'value': 'banana'}],
 'vehicles': [{'value': 'cars'}]}

または、 jsonpath-ng を使用:

>>> [d['value'] for key, value in dd.items() for d in value]
['Apple', 'banana', 'cars']
>>> [m.value for m in jsonpath_ng.parse('*.[*].value').find(dd)]
['Apple', 'banana', 'cars']

findはマッチオブジェクトを返します。マッチオブジェクトには、各アイテムへの直接パスなど、マッチした値だけでなく、あらゆる種類のものが含まれています。しかし、より複雑な式の場合、各'*.[*].value'の内包句の代わりに*のようなパスを指定できると、大きな違いが生じます。さらに、JSONPathは言語に依存しない仕様であり、デバッグには非常に便利な オンラインテスター さえあります。

3
abarnert

私はあなたが探しているものを次のように簡単に与えると思います。

In[5]: ll = [{'value': 'Apple', 'blah': 2}, {'value': 'banana', 'blah': 3} , {'value': 'cars', 'blah':4}]
In[6]: ld = [d.get('value', None) for d in ll]
In[7]: ld
Out[7]: ['Apple', 'banana', 'cars']

maplambdaを組み合わせてこれを行うこともできますが、リストの理解はよりエレガントでPythonicに見えます。

入力リストを小さくするには理解が必要ですが、入力が本当に大きい場合は、ジェネレーターが理想的な方法だと思います。

In[11]: Gd = (d.get('value', None) for d in ll)
In[12]: Gd
Out[12]: <generator object <genexpr> at 0x7f5774568b10>
In[13]: '-'.join(Gd)
Out[13]: 'Apple-banana-cars'

以下は、より大きな入力に対するすべての可能なソリューションの比較です

 In[2]: l = [{'value': 'Apple', 'blah': 2}, {'value': 'banana', 'blah': 3} , {'value': 'cars', 'blah':4}] * 9000000
In[3]: def gen_version():
  ...:     for i in l:
  ...:         yield i.get('value', None)
  ...: 
In[4]: def list_comp_verison():
  ...:     return [i.get('value', None) for i in l]
  ...: 
In[5]: def list_verison():
  ...:     ll = []
  ...:     for i in l:
  ...:         ll.append(i.get('value', None))
  ...:     return ll
In[10]: def map_lambda_version():
   ...:      m = map(lambda i:i.get('value', None), l)
   ...:      return m
   ...: 
In[11]: %timeit gen_version()
172 ns ± 0.393 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
In[12]: %timeit map_lambda_version()
203 ns ± 2.31 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
In[13]: %timeit list_comp_verison()
1.61 s ± 20.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In[14]: %timeit list_verison()
2.29 s ± 4.58 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

ご覧のとおり、ジェネレーターは他のジェネレーターに比べて優れたソリューションです。マップもジェネレーターに比べて遅いので、理由はOPに任せます。

1
Rohit

非常に簡単な方法は次のとおりです。

list1=['']
j=0
for i in com_list:
    if j==0:
        list1[0]=(i['value'])
    else:
        list1.append(i['value'])
    j+=1

出力:

['アップル'、 'バナナ'、 '車']

0
Ayushi

例に従ってください-

songs = [
{"title": "happy birthday", "playcount": 4},
{"title": "AC/DC", "playcount": 2},
{"title": "Billie Jean", "playcount": 6},
{"title": "Human Touch", "playcount": 3}
]

print("===========================")
print(f'Songs --> {songs} \n')
title = list(map(lambda x : x['title'], songs))
print(f'Print Title --> {title}')

playcount = list(map(lambda x : x['playcount'], songs))
print(f'Print Playcount --> {playcount}')
print (f'Print Sorted playcount --> {sorted(playcount)}')

# Aliter -
print(sorted(list(map(lambda x: x['playcount'],songs))))
0
Mohan. A