767 Stimmen

Suche in der Python-Liste von Wörterbüchern

Nehmen wir an, ich habe dies:

[
  {"name": "Tom", "age": 10},
  {"name": "Mark", "age": 5},
  {"name": "Pam", "age": 7}
]

und durch die Suche nach "Pam" als Name möchte ich das zugehörige Wörterbuch abrufen: {name: "Pam", age: 7}

Wie kann dies erreicht werden?

941voto

Frédéric Hamidi Punkte 249635

Sie können eine Generatorausdruck :

>>> dicts = [
...     { "name": "Tom", "age": 10 },
...     { "name": "Mark", "age": 5 },
...     { "name": "Pam", "age": 7 },
...     { "name": "Dick", "age": 12 }
... ]

>>> next(item for item in dicts if item["name"] == "Pam")
{'age': 7, 'name': 'Pam'}

Wenn das Element nicht vorhanden ist, können Sie das tun, was Benutzer Matt in seinem Kommentar vorgeschlagen und einen Standard mit einer etwas anderen API bereitstellen:

next((item for item in dicts if item["name"] == "Pam"), None)

Und um den Index des Eintrags zu finden, anstatt den Eintrag selbst, können Sie aufzählen() die Liste:

next((i for i, item in enumerate(dicts) if item["name"] == "Pam"), None)

306 Stimmen

Nur um allen anderen ein wenig Zeit zu ersparen, wenn Sie einen Standardwert für den Fall benötigen, dass "Pam" einfach nicht in der Liste ist: next((item for item in dicts if item["name"] == "Pam"), None)

5 Stimmen

Was ist mit [item for item in dicts if item["name"] == "Pam"][0] ?

4 Stimmen

@Moberg, das ist immer noch ein Listenverständnis, also wird die gesamte Eingabesequenz durchlaufen, unabhängig von der Position des passenden Elements.

320voto

PaoloC Punkte 3262

Dies scheint mir der pythonischste Weg zu sein:

people = [
{'name': "Tom", 'age': 10},
{'name': "Mark", 'age': 5},
{'name': "Pam", 'age': 7}
]

filter(lambda person: person['name'] == 'Pam', people)

Ergebnis (in Python 2 als Liste zurückgegeben):

[{'age': 7, 'name': 'Pam'}]

Hinweis: In Python 3 wird ein Filterobjekt zurückgegeben. Die Python3-Lösung wäre also:

list(filter(lambda person: person['name'] == 'Pam', people))

17 Stimmen

Es ist erwähnenswert, dass diese Antwort eine Liste mit allen Übereinstimmungen für 'Pam' in Personen zurückgibt. Alternativ könnten wir eine Liste aller Personen erhalten, die nicht 'Pam' sind, indem wir den Vergleichsoperator in != ändern. +1

4 Stimmen

Es ist auch erwähnenswert, dass das Ergebnis ein Filterobjekt ist, keine Liste - wenn Sie Dinge verwenden wollen wie len() müssen Sie anrufen list() zunächst auf das Ergebnis. Oder: stackoverflow.com/questions/19182188/

0 Stimmen

@wasabigeek das ist, was mein Python 2.7 sagt: people = [ {'name': "Tom", 'age': 10}, {'name': "Mark", 'age': 5}, {'Name': "Pam", 'Alter': 7} ] r = filter(lambda person: person['name'] == 'Pam', people) type(r) list So r ist eine list

104voto

Mike N Punkte 5775

Die Antwort von @Frédéric Hamidi ist großartig. In Python 3.x ist die Syntax für .next() leicht verändert. Daher eine kleine Änderung:

>>> dicts = [
     { "name": "Tom", "age": 10 },
     { "name": "Mark", "age": 5 },
     { "name": "Pam", "age": 7 },
     { "name": "Dick", "age": 12 }
 ]
>>> next(item for item in dicts if item["name"] == "Pam")
{'age': 7, 'name': 'Pam'}

Wie in den Kommentaren von @Matt erwähnt, können Sie einen Standardwert als solchen hinzufügen:

>>> next((item for item in dicts if item["name"] == "Pam"), False)
{'name': 'Pam', 'age': 7}
>>> next((item for item in dicts if item["name"] == "Sam"), False)
False
>>>

6 Stimmen

Dies ist die beste Antwort für Python 3.x. Wenn Sie ein bestimmtes Element aus den Dicts benötigen, z. B. Alter, können Sie schreiben: next((item.get('age') for item in dicts if item["name"] == "Pam"), False)

79voto

Sie können eine Listenverstehen :

def search(name, people):
    return [element for element in people if element['name'] == name]

9 Stimmen

Das ist gut, weil es alle Übereinstimmungen zurückgibt, wenn es mehr als eine gibt. Nicht genau das, wonach die Frage gefragt hat, aber es ist das, was ich brauchte! Danke!

2 Stimmen

Beachten Sie auch, dass dies eine Liste zurückgibt!

0 Stimmen

Ist es möglich, zwei Bedingungen zu übergeben, z. B. wenn element['name'] == name und element['age'] == age? Ich habe es ausprobiert, aber es scheint nicht zu funktionieren, sagt Element ist undefiniert auf die zweite Bedingung.

60voto

user136036 Punkte 8980

Ich habe verschiedene Methoden getestet, um eine Liste von Wörterbüchern zu durchsuchen und die Wörterbücher zurückzugeben, in denen der Schlüssel x einen bestimmten Wert hat.

Ergebnisse:

  • Geschwindigkeit: Listenverständnis > Generatorausdruck >> normale Listeniteration >>> Filter.
  • Alle skalieren linear mit der Anzahl der Dicts in der Liste (10x Listengröße -> 10x Zeit).
  • Die Anzahl der Schlüssel pro Wörterbuch wirkt sich bei großen Mengen (Tausende) von Schlüsseln nicht wesentlich auf die Geschwindigkeit aus. Bitte sehen Sie sich dieses von mir berechnete Diagramm an: https://imgur.com/a/quQzv (Methodennamen siehe unten).

Alle Tests, die mit Python 3.6 .4, W7x64.

from random import randint
from timeit import timeit

list_dicts = []
for _ in range(1000):     # number of dicts in the list
    dict_tmp = {}
    for i in range(10):   # number of keys for each dict
        dict_tmp[f"key{i}"] = randint(0,50)
    list_dicts.append( dict_tmp )

def a():
    # normal iteration over all elements
    for dict_ in list_dicts:
        if dict_["key3"] == 20:
            pass

def b():
    # use 'generator'
    for dict_ in (x for x in list_dicts if x["key3"] == 20):
        pass

def c():
    # use 'list'
    for dict_ in [x for x in list_dicts if x["key3"] == 20]:
        pass

def d():
    # use 'filter'
    for dict_ in filter(lambda x: x['key3'] == 20, list_dicts):
        pass

Ergebnisse:

1.7303 # normal list iteration 
1.3849 # generator expression 
1.3158 # list comprehension 
7.7848 # filter

0 Stimmen

Ich habe die Funktion z() hinzugefügt, die next implementiert, wie von Frédéric Hamidi oben beschrieben. Hier sind die Ergebnisse aus dem Py-Profil.

0 Stimmen

Weiß jemand, warum eine Liste, die die c() wäre so viel schneller als eine einfache Iteration über die Liste a()

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X