Gegeben:
[
{"name": "Tom", "age": 10},
{"name": "Mark", "age": 5},
{"name": "Pam", "age": 7}
]
Wie suche ich nach name == "Pam"
um das entsprechende Wörterbuch unten abzurufen?
{"name": "Pam", "age": 7}
Hellnar
Gegeben:
[
{"name": "Tom", "age": 10},
{"name": "Mark", "age": 5},
{"name": "Pam", "age": 7}
]
Wie suche ich nach name == "Pam"
um das entsprechende Wörterbuch unten abzurufen?
{"name": "Pam", "age": 7}
Frédéric Hamidi
Sie können eine verwenden 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 Sie damit umgehen müssen, dass das Element nicht vorhanden ist, können Sie das tun, was Benutzer Matt in seinem Kommentar vorgeschlagen hat, 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 Elements anstelle des Elements selbst zu finden, können Sie aufzählen() Die Liste:
next((i for i, item in enumerate(dicts) if item["name"] == "Pam"), None)
Nur um jemandem etwas Zeit zu sparen, wenn Sie einen Standardwert für das Ereignis benötigen, “Pam” ist einfach nicht in der Liste: next((item for item in dicts if item[“name”] == “Pam”), keine)
– Matt
27. November 2012 um 22:08 Uhr
Wie wäre es mit [item for item in dicts if item["name"] == "Pam"][0]
?
– Möberg
9. Oktober 2014 um 11:30 Uhr
@Moberg, das ist immer noch ein Listenverständnis, daher wird die gesamte Eingabesequenz unabhängig von der Position des übereinstimmenden Elements durchlaufen.
– Frédéric Hamidi
9. Oktober 2014 um 12:02 Uhr
Dadurch wird ein Stoppiterationsfehler ausgelöst, wenn der Schlüssel nicht im Wörterbuch vorhanden ist
– Kishan Mehta
5. Juni 2018 um 12:25 Uhr
@Siemkowski: dann hinzufügen enumerate()
um einen laufenden Index zu generieren: next(i for i, item in enumerate(dicts) if item["name"] == "Pam")
.
– Martijn Pieters
♦
22. November 2018 um 12:56 Uhr
PaoloC
Das sieht für mich am pythonischsten aus:
people = [
{'name': "Tom", 'age': 10},
{'name': "Mark", 'age': 5},
{'name': "Pam", 'age': 7}
]
filter(lambda person: person['name'] == 'Pam', people)
Ergebnis (als Liste in Python 2 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))
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
– Onema
12. November 2015 um 22:25 Uhr
Erwähnenswert ist auch, dass das Ergebnis ein Filterobjekt ist, keine Liste – wenn Sie Dinge wie verwenden möchten len()
du musst anrufen list()
zuerst auf das Ergebnis. Oder: stackoverflow.com/questions/19182188/…
– wasabigeek
21. Dezember 2017 um 16:06 Uhr
@wasabigeek das sagt mein Python 2.7: people = [ {‘name’: “Tom”, ‘age’: 10}, {‘name’: “Mark”, ‘age’: 5}, {‘name’: “Pam”, ‘age’: 7} ] r = filter(lambda Person: Person[‘name’] == ‘Pam’, Leute) type(r) list So r
ist ein list
– PaoloC
26. Dezember 2017 um 14:32 Uhr
Listenverständnisse gelten als pythonischer als map/filter/reduce: stackoverflow.com/questions/5426754/google-python-style-guide
– jrc
11. November 2019 um 12:58 Uhr
Holen Sie sich das erste Spiel: next(filter(lambda x: x['name'] == 'Pam', dicts))
– xgMz
12. Dezember 2019 um 19:24 Uhr
Mike N
@ Frédéric Hamidis Antwort ist großartig. In Python 3.x ist die Syntax für .next()
leicht verändert. Daher eine kleine Modifikation:
>>> 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
>>>
Dies ist die beste Antwort für Python 3.x. Wenn Sie ein bestimmtes Element aus den Diktaten benötigen, z. B. das Alter, können Sie Folgendes schreiben: next((item.get(‘age’) for item in dicts if item[“name”] == “Pam”), falsch)
– Flüsterer
9. Januar 2019 um 7:44 Uhr
Sie können eine verwenden Listenverständnis:
def search(name, people):
return [element for element in people if element['name'] == name]
Ich habe verschiedene Methoden getestet, um eine Liste von Wörterbüchern durchzugehen und die Wörterbücher zurückzugeben, in denen der Schlüssel x einen bestimmten Wert hat.
Ergebnisse:
Alle Tests mit gemacht 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
Ich habe die Funktion z() hinzugefügt, die next implementiert, wie oben von Frédéric Hamidi gezeigt. Hier sind die Ergebnisse des Py-Profils.
– Leon
24. März 2019 um 1:53 Uhr
Weiß jemand, warum eine Liste Comprehension c()
wäre so viel schneller, als einfach über die Liste zu iterieren a()
– wissenssuchender
7. Oktober 2022 um 0:28 Uhr
Rick Robinson
people = [
{'name': "Tom", 'age': 10},
{'name': "Mark", 'age': 5},
{'name': "Pam", 'age': 7}
]
def search(name):
for p in people:
if p['name'] == name:
return p
search("Pam")
Ich habe die Funktion z() hinzugefügt, die next implementiert, wie oben von Frédéric Hamidi gezeigt. Hier sind die Ergebnisse des Py-Profils.
– Leon
24. März 2019 um 1:53 Uhr
Weiß jemand, warum eine Liste Comprehension c()
wäre so viel schneller, als einfach über die Liste zu iterieren a()
– wissenssuchender
7. Oktober 2022 um 0:28 Uhr
Haben Sie schon einmal das Pandas-Paket ausprobiert? Es ist perfekt für diese Art von Suchaufgabe und auch optimiert.
import pandas as pd
listOfDicts = [
{"name": "Tom", "age": 10},
{"name": "Mark", "age": 5},
{"name": "Pam", "age": 7}
]
# Create a data frame, keys are used as column headers.
# Dict items with the same key are entered into the same respective column.
df = pd.DataFrame(listOfDicts)
# The pandas dataframe allows you to pick out specific values like so:
df2 = df[ (df['name'] == 'Pam') & (df['age'] == 7) ]
# Alternate syntax, same thing
df2 = df[ (df.name == 'Pam') & (df.age == 7) ]
Ich habe unten ein wenig Benchmarking hinzugefügt, um die schnelleren Laufzeiten von Pandas in größerem Maßstab zu veranschaulichen, dh über 100.000 Einträge:
setup_large="dicts = [];\
[dicts.extend(({ "name": "Tom", "age": 10 },{ "name": "Mark", "age": 5 },\
{ "name": "Pam", "age": 7 },{ "name": "Dick", "age": 12 })) for _ in range(25000)];\
from operator import itemgetter;import pandas as pd;\
df = pd.DataFrame(dicts);"
setup_small="dicts = [];\
dicts.extend(({ "name": "Tom", "age": 10 },{ "name": "Mark", "age": 5 },\
{ "name": "Pam", "age": 7 },{ "name": "Dick", "age": 12 }));\
from operator import itemgetter;import pandas as pd;\
df = pd.DataFrame(dicts);"
method1 = '[item for item in dicts if item["name"] == "Pam"]'
method2 = 'df[df["name"] == "Pam"]'
import timeit
t = timeit.Timer(method1, setup_small)
print('Small Method LC: ' + str(t.timeit(100)))
t = timeit.Timer(method2, setup_small)
print('Small Method Pandas: ' + str(t.timeit(100)))
t = timeit.Timer(method1, setup_large)
print('Large Method LC: ' + str(t.timeit(100)))
t = timeit.Timer(method2, setup_large)
print('Large Method Pandas: ' + str(t.timeit(100)))
#Small Method LC: 0.000191926956177
#Small Method Pandas: 0.044392824173
#Large Method LC: 1.98827004433
#Large Method Pandas: 0.324505090714
und method3 = “””df.query(“name == ‘Pam'”)”””, ist zwar etwas langsamer als Methode 2 für kleine Datensätze (immer noch 2 Größenordnungen schneller als LC), aber auf meinem Computer doppelt so schnell für den größeren Datensatz
– Emmagras
9. Februar 2022 um 13:25 Uhr