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ć?

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]

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)).


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]

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.


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ć.


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))))

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

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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.