web-dev-qa-db-fra.com

Python: extrait un dict d'une liste basée sur quelque chose qu'il contient

Je dois pouvoir trouver un élément dans une list (un article dans ce cas-ci étant une dict) basé sur une valeur à l'intérieur de cette dict. La structure de la list que je dois traiter ressemble à ceci:

[
    {
        'title': 'some value',
        'value': 123.4,
        'id': 'an id'
    },
    {
        'title': 'another title',
        'value': 567.8,
        'id': 'another id'
    },
    {
        'title': 'last title',
        'value': 901.2,
        'id': 'yet another id'
    }
]

Mises en garde: title et value peuvent être n'importe quelle valeur (et la même chose), id serait unique.

Je dois pouvoir obtenir une dict de cette list basée sur une id unique. Je sais que cela peut être fait en utilisant des boucles, mais cela semble lourd et j'ai le sentiment qu'il existe une méthode évidente de faire cela que je ne vois pas grâce à la fonte des cerveaux.

37
johneth
my_item = next((item for item in my_list if item['id'] == my_unique_id), None)

Cela parcourt la liste jusqu'à ce qu'il trouve le premier élément correspondant à my_unique_id, puis s'arrête. Il ne stocke aucune liste intermédiaire en mémoire (en utilisant une expression génératrice) et ne nécessite pas de boucle explicite. Il définit my_item sur None si aucun objet n'a été trouvé. C'est à peu près la même chose que

for item in my_list:
    if item['id'] == my_unique_id:
        my_item = item
        break
else:
    my_item = None

Les clauses else des boucles for sont utilisées lorsque la boucle n'est pas terminée par une instruction break.

68
agf

Si vous devez le faire plusieurs fois, vous devez recréer un dictionnaire indexé par identifiant avec votre liste: 

keys = [item['id'] for item in initial_list]
new_dict = dict(Zip(keys, initial_list)) 

>>>{
    'yet another id': {'id': 'yet another id', 'value': 901.20000000000005, 'title': 'last title'}, 
    'an id': {'id': 'an id', 'value': 123.40000000000001, 'title': 'some value'}, 
    'another id': {'id': 'another id', 'value': 567.79999999999995, 'title': 'another title'}
}

ou d'une manière one-liner comme suggéré par agf: 

new_dict = dict((item['id'], item) for item in initial_list)
17
Cédric Julien

Vous pouvez créer une fonction simple à cette fin:

lVals = [{'title': 'some value', 'value': 123.4,'id': 'an id'},
 {'title': 'another title', 'value': 567.8,'id': 'another id'},
 {'title': 'last title', 'value': 901.2, 'id': 'yet another id'}]

def get_by_id(vals, expId): return next(x for x in vals if x['id'] == expId)

get_by_id(lVals, 'an id')
>>> {'value': 123.4, 'title': 'some value', 'id': 'an id'}
0
Artsiom Rudzenka
In [2]: test_list
Out[2]: 
[{'id': 'an id', 'title': 'some value', 'value': 123.40000000000001},
 {'id': 'another id', 'title': 'another title', 'value': 567.79999999999995},
 {'id': 'yet another id', 'title': 'last title', 'value': 901.20000000000005}]

In [3]: [d for d in test_list if d["id"] == "an id"]
Out[3]: [{'id': 'an id', 'title': 'some value', 'value': 123.40000000000001}]

Utiliser la compréhension de la liste

0
TyrantWave