338 votes

Trouver un objet dans la liste dont l'attribut est égal à une certaine valeur (qui répond à une condition quelconque).

J'ai une liste d'objets. Je veux trouver un (premier ou autre) objet dans cette liste qui a un attribut (ou un résultat de méthode - autre) égal à value .

Quel est le meilleur moyen de le trouver ?

Voici un cas d'essai :

class Test:
    def __init__(self, value):
        self.value = value

import random

value = 5

test_list = [Test(random.randint(0,100)) for x in range(1000)]

# that I would do in Pascal, I don't believe it's anywhere near 'Pythonic'
for x in test_list:
    if x.value == value:
        print "i found it!"
        break

Je pense que l'utilisation de générateurs et reduce() ne fera aucune différence, car il s'agira toujours d'itérer dans la liste.

ps. : Equation pour value n'est qu'un exemple. Bien sûr, nous voulons obtenir un élément qui répond à n'importe quelle condition.

657voto

agf Points 45052
next((x for x in test_list if x.value == value), None)

Elle récupère le premier élément de la liste qui correspond à la condition, et renvoie None si aucun élément ne correspond. C'est la forme à expression unique que je préfère.

Cependant,

for x in test_list:
    if x.value == value:
        print("i found it!")
        break

La version naïve avec rupture de boucle est parfaitement pythonique - elle est concise, claire et efficace. Pour la faire correspondre au comportement du one-liner :

for x in test_list:
    if x.value == value:
        print("i found it!")
        break
else:
    x = None

Cela permettra d'attribuer None a x si tu ne le fais pas break hors de la boucle.

39voto

Nima Mousavi Points 978

Puisque cela n'a pas été mentionné, juste pour compléter. Le bon vieux filtre pour filtrer vos éléments à filtrer.

Programmation fonctionnelle ftw.

####### Set Up #######
class X:

    def __init__(self, val):
        self.val = val

elem = 5

my_unfiltered_list = [X(1), X(2), X(3), X(4), X(5), X(5), X(6)]

####### Set Up #######

### Filter one liner ### filter(lambda x: condition(x), some_list)
my_filter_iter = filter(lambda x: x.val == elem, my_unfiltered_list)
### Returns a flippin' iterator at least in Python 3.5 and that's what I'm on

print(next(my_filter_iter).val)
print(next(my_filter_iter).val)
print(next(my_filter_iter).val)

### [1, 2, 3, 4, 5, 5, 6] Will Return: ###
# 5
# 5
# Traceback (most recent call last):
#   File "C:\Users\mousavin\workspace\Scripts\test.py", line 22, in <module>
#     print(next(my_filter_iter).value)
# StopIteration

# You can do that None stuff or whatever at this point, if you don't like exceptions.

Je sais qu'en général, en python, les compréhensions de listes sont préférées ou au moins c'est ce que j'ai lu, mais je ne vois pas le problème pour être honnête. Bien sûr, Python n'est pas un langage FP, mais Map / Reduce / Filter sont parfaitement lisibles et constituent le plus standard des cas d'utilisation standard en programmation fonctionnelle.

Alors voilà. Connaissez votre programmation fonctionnelle.

liste des conditions de filtrage

Ce ne sera pas plus facile que ça :

next(filter(lambda x: x.val == value,  my_unfiltered_list)) # Optionally: next(..., None) or some other default value to prevent Exceptions

30voto

m.n76 Points 43

Un exemple simple : Nous avons le tableau suivant

li = [{"id":1,"name":"ronaldo"},{"id":2,"name":"messi"}]

Maintenant, nous voulons trouver l'objet dans le tableau qui a l'id égal à 1

  1. Utiliser la méthode next avec compréhension des listes

    next(x for x in li if x["id"] == 1 )

  2. Utiliser la compréhension de liste et retourner le premier élément

    [x for x in li if x["id"] == 1 ][0]

  3. Fonction personnalisée

    def find(arr , id): for x in arr: if x["id"] == id: return x find(li , 1)

La sortie de toutes les méthodes ci-dessus est {'id': 1, 'name': 'ronaldo'}

3voto

Illud Points 103

Vous pourriez faire quelque chose comme ceci

dict = [{
   "id": 1,
   "name": "Doom Hammer"
 },
 {
    "id": 2,
    "name": "Rings ov Saturn"
 }
]

for x in dict:
  if x["id"] == 2:
    print(x["name"])

C'est ce que j'utilise pour trouver les objets dans un long tableau d'objets.

3voto

Colin Hicks Points 286

Vieille question mais je l'utilise assez fréquemment (pour la version 3.8). C'est un peu un sel syntaxique, mais il a l'avantage par rapport à la première réponse que vous pourriez récupérer une liste de résultats (s'il y en a plusieurs) en supprimant simplement l'élément [0] et la valeur par défaut est toujours None si rien n'est trouvé. Pour toute autre condition, il suffit de modifier le paramètre x.value==value à ce que vous cherchez.

_[0] if (_:=[x for x in test_list if x.value==value]) else None

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X