J'ai une liste de dictionnaires. Pour chaque dict, je dois transmettre l'une de ses propriétés à une fonction, puis attribuer une nouvelle propriété en fonction du résultat de cette fonction.
Par exemple: J'ai une liste de pages d'un site. Je dois les parcourir et, en fonction de l'URL, attribuer le nom de l'auteur à une propriété dans le dict.
pages = [??? for page in pages]
Cela fonctionne. Mais est encombré et ne semble pas pythonique. pages [index]
ressemble à une chose que je ne devrais pas avoir à faire en Python.
Y a-t-il un moyen de le faire via une compréhension de liste? Ou une autre manière plus pythonique?
for index, page in enumerate(pages): pages[index]['author'] = get_author(page['url'])
3 Réponses :
Une compréhension de liste construit une liste à partir d'une liste existante. Dans votre cas, vous souhaitez mettre à jour les éléments de liste existants. Une compréhension de liste est inappropriée pour ce travail.
Votre solution peut cependant être quelque peu améliorée:
for page in pages: page['author'] = get_author(page['url'])
Je pouvais me tromper, mais j'avais cru comprendre que la modification directe de page
ne propagerait pas ce changement aux pages
. Je vais vérifier
@snazzybouche ouais, vous avez tort. list
est modifiable et page
sera une référence à l'objet existant dans pages
, pas une copie ou quelque chose comme ça. Cela marche.
@snazzybouche Vous pensez probablement à réassigner au nom de la variable; quelque chose comme page = ...
. Dans ce cas, vous modifiez l'objet pointé par page
en place, donc ça ira.
@gmds Oui, on dirait que c'est là que je me suis mêlé. J'allais dire que j'ai utilisé enumerate beaucoup plus que je n'aurais dû, mais si c'est le cas, je ne me suis pas trop mal débrouillé.
Vous pouvez utiliser une telle liste
compréhension:
[{'url': 1, 'author': 'hello'}, {'url': 2, 'author': 'bye'}]
Cela crée un nouveau Notez qu'il ne modifie pas la Exemple: dict
pour chaque dict code> avec une clé supplémentaire,
author
, basée sur la valeur de get_author
appliquée à la valeur correspondant à la clé url
. p > list
d'origine .def get_author(i):
if i == 1:
return 'hello'
else:
return 'bye'
pages = [{'url': 1},
{'url': 2}]
result = [{**page, **{'author': get_author(page['url'])}} for page in pages]
print(result)
Sortie:
result = [{**page, 'author': get_author(page['url'])} for page in pages] # This works too: result = [dict(**page, author=get_author(page['url'])) for page in pages] # but is less preferred because it will fail for input containing non-string keys
Je peux voir deux solutions "pythoniques":
pages = [p.update(author=get_author(p['url'])) or p for p in pages]
pages = [{**p, 'author': get_author(p['url'])} for p in pages]
Puisque p.update () renvoie None, None ou p
sera toujours la version mise à jour de p.
Le premier semble être plus lisible mais je pense que le second bat le premier en performance.
Une compréhension de liste construit une liste à partir d'une liste existante. Dans votre cas, vous souhaitez mettre à jour les éléments de liste existants. Une compréhension de liste est inappropriée pour ce travail.
@DYZ a du sens. Y a-t-il une alternative ici?