Pobieranie listy wartości z listy poleceń

184

Mam listę takich nakazów:

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

chcę ['apple', 'banana', 'cars']

Jak najlepiej to zrobić?

SuperString
źródło

Odpowiedzi:

324

Zakładając, że każdy dykt ma valueklucz, możesz pisać (zakładając, że twoja lista jest nazwana l)

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

Jeśli valuebrakuje, możesz użyć

[d['value'] for d in l if 'value' in d]
Ismail Badawi
źródło
8
Aby usunąć brakującą wartość klucza, można również użyć d.get ("key_to_lookup", "alternate_value"). Wtedy będzie wyglądać następująco: [d.get ('value', 'alt') for d in l]. Jeśli wartość nie jest obecna jako klucz, zwróci po prostu „alt”.
abhinav
Dzięki za rozwiązanie
Ajay Kumar
Ta „magia” jest znana jako rozumienie list docs.python.org/3/tutorial/ ...
William Ardila
34

Oto inny sposób na zrobienie tego za pomocą funkcji map () i lambda:

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

gdzie ja jest listą. Uważam, że ten sposób jest „najseksowniejszy”, ale zrobiłbym to za pomocą rozumienia list.

Aktualizacja: w przypadku, gdy brakuje tej „wartości” jako klucza:

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

Aktualizacja: Nie jestem też wielkim fanem lambd, wolę nazywać rzeczy ... tak bym to zrobił mając to na uwadze:

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

Poszedłbym nawet dalej i stworzył jedyną funkcję, która wyraźnie określa, co chcę osiągnąć:

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

W Pythonie 3, ponieważ mapzwraca iterator, użyj, listaby zwrócić listę, np list(map(operator.itemgetter('value'), l)).

Anler
źródło
1
Obrzydliwy! Zrozumienie listy ma tutaj dużo więcej sensu.
Mike Graham
4
Jeśli masz zamiar użyć pierwszego map, użyj operator.itemgetter('value'), a nie pliku lambda.
agf
18
[x['value'] for x in list_of_dicts]
Michał Trybus
źródło
lub [d.getkey ('value') for d in dict_list]
rplnt
1
@rpInt Um, nie ma czegoś takiego jak getkey… masz na myśli d.get('value')? To byłoby to samo, co rozumienie drugiej listy @ isbadawi, a nie Michała.
agf
3
Tak, przepraszam, miałem na myśli dostać. I miałem to na myśli jako coś, co nie zgłosi wyjątku, jeśli brakuje klucza. Ale rozwiązanie @ isbadawi jest lepsze, ponieważ get () poda None (lub cokolwiek określimy jako domyślne), gdy brakuje klucza.
rplnt
5

W bardzo prostym przypadku, takim jak ten, zrozumienie, jak w przypadku odpowiedzi Ismaila Badawiego, jest zdecydowanie właściwą drogą.

Ale kiedy sprawy stają się bardziej skomplikowane i musisz zacząć pisać złożone zdania składające się z wielu zdań lub wyrażenia zagnieżdżone, w których występują złożone wyrażenia, warto przyjrzeć się innym alternatywom. Istnieje kilka różnych (quasi-) standardowych sposobów określania wyszukiwań w stylu XPath w zagnieżdżonych strukturach dyktowania i listy, takich jak JSONPath, DPath i KVC. Są dla nich fajne biblioteki na PyPI.

Oto przykład z biblioteką o nazwie dpath, pokazujący, jak może uprościć coś nieco bardziej skomplikowanego:

>>> 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'}]}

Lub używając 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']

Ten na pierwszy rzut oka może nie wyglądać tak prosto, ponieważ findzwraca dopasowywanie obiektów, które zawierają wszelkiego rodzaju rzeczy oprócz tylko dopasowanej wartości, takie jak ścieżka bezpośrednio do każdego elementu. Ale w przypadku bardziej złożonych wyrażeń możliwość określenia ścieżki, takiej jak '*.[*].value'zamiast klauzuli ze zrozumieniem dla każdego, *może mieć duże znaczenie. Ponadto JSONPath to specyfikacja niezależna od języka, a nawet testerzy online mogą być bardzo przydatni do debugowania.

abarnert
źródło
1

Myślę, że tak proste, jak poniżej, dałoby ci to, czego szukasz.

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']

Możesz to zrobić za pomocą kombinacji mapi, lambdaale rozumienie listy wygląda bardziej elegancko i pytonicznie.

W przypadku mniejszych list wejściowych dobrze jest zrobić, ale jeśli dane wejściowe są naprawdę duże, myślę, że generatory są idealnym sposobem.

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'

Oto porównanie wszystkich możliwych rozwiązań dla większego wkładu

 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)

Jak widać, generatory są lepszym rozwiązaniem w porównaniu do innych, mapa jest również wolniejsza w porównaniu do generatora, dlatego pozostawię OP, aby się dowiedzieć.

Rohit
źródło
1

Podążaj za przykładem --

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))))
Mohan. ZA
źródło
1

Pobrać kluczowe wartości z listy słowników w Pythonie?

  1. Pobrać kluczowe wartości z listy słowników w Pythonie?

Dawny:

data = 
[{'obj1':[{'cpu_percentage':'15%','ram':3,'memory_percentage':'66%'}]},
{'obj2': [{'cpu_percentage':'0','ram':4,'memory_percentage':'35%'}]}]

dla d w danych:

  for key,value in d.items(): 

      z ={key: {'cpu_percentage': d['cpu_percentage'],'memory_percentage': d['memory_percentage']} for d in value} 
      print(z)

Wynik:

{'obj1': {'cpu_percentage': '15%', 'memory_percentage': '66%'}}
{'obj2': {'cpu_percentage': '0', 'memory_percentage': '35%'}}
Kalyani B.
źródło
-2

Bardzo prostym sposobem na to jest:

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

Wynik:

[„jabłko”, „banan”, „samochody”]

Ayushi
źródło