Abrufen einer Werteliste aus einer Liste von Diktaten

184

Ich habe eine Liste solcher Diktate:

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

Ich will ['apple', 'banana', 'cars']

Was ist der beste Weg, dies zu tun?

SuperString
quelle

Antworten:

324

Angenommen, jedes Diktat hat einen valueSchlüssel, können Sie schreiben (vorausgesetzt, Ihre Liste heißt benannt l).

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

Wenn valuemöglicherweise fehlt, können Sie verwenden

[d['value'] for d in l if 'value' in d]
Ismail Badawi
quelle
8
Um fehlende Werte für einen Schlüssel zu behandeln, kann man auch d.get ("key_to_lookup", "alternative_value") verwenden. Dann sieht es so aus: [d.get ('value', 'alt') für d in l]. Wenn der Wert nicht als Schlüssel vorhanden ist, wird einfach 'alt' zurückgegeben.
Abhinav
Vielen Dank für die Lösung
Ajay Kumar
Diese "Magie" ist bekannt als Listenverständnis docs.python.org/3/tutorial/…
William Ardila
34

Hier ist eine andere Möglichkeit, dies mit den Funktionen map () und lambda zu tun:

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

wo l ist die Liste. Ich sehe diesen Weg "sexiest", aber ich würde es mit dem Listenverständnis tun.

Update: Falls dieser 'Wert' als Schlüssel fehlt, verwenden Sie:

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

Update: Ich bin auch kein großer Fan von Lambdas, ich nenne lieber Dinge ... so würde ich es in diesem Sinne machen:

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

Ich würde sogar noch weiter gehen und eine einzige Funktion erstellen, die explizit sagt, was ich erreichen möchte:

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

mapVerwenden Sie listin Python 3, da ein Iterator zurückgegeben wird , um eine Liste zurückzugeben, z list(map(operator.itemgetter('value'), l)).

Anler
quelle
1
Brutto! Das Listenverständnis macht hier viel mehr Sinn.
Mike Graham
4
Wenn Sie die erste verwenden mapmöchten operator.itemgetter('value'), verwenden Sie nicht a lambda.
Agf
18
[x['value'] for x in list_of_dicts]
Michał Trybus
quelle
oder [d.getkey ('value') für d in dict_list]
rplnt
1
@rpInt Ähm, es gibt keine getkey... meinst du d.get('value')? Das wäre dasselbe wie @ isbadawis 2. Listenverständnis, nicht das von Michal.
Agf
3
Ja, sorry, ich wollte bekommen. Und ich meinte es als etwas, das keine Ausnahme auslöst, wenn der Schlüssel fehlt. Die Lösung von @ isbadawi ist jedoch besser, da get () None (oder was auch immer wir als Standard angeben) liefert, wenn der Schlüssel fehlt.
rplnt
5

Für einen sehr einfachen Fall wie diesen ist ein Verständnis wie in Ismail Badawis Antwort definitiv der richtige Weg.

Wenn die Dinge jedoch komplizierter werden und Sie mit dem Schreiben von Mehrklauseln oder verschachtelten Verständnissen mit komplexen Ausdrücken beginnen müssen, sollten Sie nach anderen Alternativen suchen. Es gibt verschiedene (quasi) Standardmethoden zum Festlegen von XPath-Suchvorgängen in verschachtelten Diktat- und Listenstrukturen wie JSONPath, DPath und KVC. Und es gibt nette Bibliotheken auf PyPI für sie.

Hier ist ein Beispiel mit der genannten Bibliothek dpath, das zeigt, wie es etwas etwas komplizierteres vereinfachen kann:

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

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

Dieser sieht auf den ersten Blick möglicherweise nicht ganz so einfach aus, da findÜbereinstimmungsobjekte zurückgegeben werden, die alle Arten von Dingen außer nur dem übereinstimmenden Wert enthalten, z. B. einen Pfad direkt zu jedem Element. Bei komplexeren Ausdrücken kann es jedoch einen großen Unterschied machen , einen Pfad wie '*.[*].value'anstelle einer Verständnisklausel für jeden anzugeben *. Außerdem ist JSONPath eine sprachunabhängige Spezifikation, und es gibt sogar Online-Tester , die beim Debuggen sehr praktisch sein können.

abarnert
quelle
1

Ich denke, so einfach wie unten würde Ihnen geben, wonach Sie suchen.

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

Sie können dies auch mit einer Kombination aus mapund tun, lambdaaber das Listenverständnis sieht eleganter und pythonischer aus.

Für eine kleinere Eingabeliste ist das Verständnis ein guter Weg, aber wenn die Eingabe wirklich groß ist, sind Generatoren meiner Meinung nach der ideale Weg.

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'

Hier ist ein Vergleich aller möglichen Lösungen für größere Eingaben

 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)

Wie Sie sehen können, sind Generatoren im Vergleich zu den anderen eine bessere Lösung. Die Karte ist im Vergleich zum Generator auch langsamer, da ich es dem OP überlassen werde, dies herauszufinden.

Rohit
quelle
1

Folge dem Beispiel --

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. EIN
quelle
1

Schlüsselwerte aus der Liste der Wörterbücher in Python abrufen?

  1. Schlüsselwerte aus der Liste der Wörterbücher in Python abrufen?

Ex:

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

für d in Daten:

  for key,value in d.items(): 

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

Ausgabe:

{'obj1': {'cpu_percentage': '15%', 'memory_percentage': '66%'}}
{'obj2': {'cpu_percentage': '0', 'memory_percentage': '35%'}}
Kalyani B.
quelle
-2

Ein sehr einfacher Weg, dies zu tun, ist:

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

Ausgabe:

['Apfel', 'Banane', 'Autos']

Ayushi
quelle