930 votes

Python : Recherche dans une liste

Je suis tombé sur ceci :

item = someSortOfSelection()
if item in myList:
    doMySpecialFunction(item)

mais parfois cela ne fonctionne pas avec tous mes éléments, comme s'ils n'étaient pas reconnus dans la liste (alors qu'il s'agit d'une liste de chaînes).

Est-ce la façon la plus "pythique" de trouver un élément dans une liste ? if x in l: ?

3 votes

C'est tout à fait correct et devrait fonctionner si item est égal à l'un des éléments contenus dans myList .

1 votes

Vous voulez dire que c'est la bonne façon de faire les choses ? dans mes différents essais, il y avait peut-être des espaces, et des retours à la ligne qui s'entremêlaient... je voulais juste être sûr que c'est la bonne façon d'implémenter "find in list" (en général)

1748voto

Niklas B. Points 40619

Pour ce qui est de votre première question : ce code est tout à fait correct et devrait fonctionner si item est égal à l'un des éléments contenus dans myList . Peut-être que vous essayez de trouver une chaîne qui n'est pas exactement correspond à l'un des éléments ou peut-être utilisez-vous une valeur flottante qui souffre d'imprécision.

Quant à votre deuxième question : Il y a en fait plusieurs façons de "trouver" des choses dans les listes.

Vérifier si quelque chose est à l'intérieur

C'est le cas d'utilisation que vous décrivez : Vérifier si quelque chose est à l'intérieur d'une liste ou non. Comme vous le savez, vous pouvez utiliser la fonction in opérateur pour cela :

3 in [1, 2, 3] # => True

Filtrer une collection

C'est-à-dire trouver tous les éléments d'une séquence qui répondent à une certaine condition. Vous pouvez utiliser la compréhension de liste ou les expressions de générateur pour cela :

matches = [x for x in lst if fulfills_some_condition(x)]
matches = (x for x in lst if x > 6)

Ce dernier renverra un générateur que vous pouvez imaginer comme une sorte de liste paresseuse qui ne sera construite que lorsque vous l'aurez parcourue. Au fait, la première est exactement équivalente à

matches = filter(fulfills_some_condition, lst)

dans Python 2. Vous pouvez voir ici les fonctions d'ordre supérieur à l'œuvre. En Python 3, filter ne retourne pas une liste, mais un objet de type générateur.

Trouver la première occurrence

Si vous ne voulez que la première chose qui correspond à une condition (mais que vous ne savez pas encore laquelle), vous pouvez utiliser une boucle for (en utilisant éventuellement la fonction else également, ce qui n'est pas vraiment connu). Vous pouvez également utiliser

next(x for x in lst if ...)

qui renvoie la première correspondance ou lève un StopIteration si aucun n'est trouvé. Alternativement, vous pouvez utiliser

next((x for x in lst if ...), [default value])

Trouver l'emplacement d'un élément

Pour les listes, il y a aussi le index qui peut parfois être utile si vous voulez connaître un certain élément est dans la liste :

[1,2,3].index(2) # => 1
[1,2,3].index(4) # => ValueError

Cependant, notez que si vous avez des doublons, .index renvoie toujours l'indice le plus bas : ......

[1,2,3,2].index(2) # => 1

S'il y a des doublons et que vous voulez tous les index, vous pouvez utiliser enumerate() à la place :

[i for i,x in enumerate([1,2,3,2]) if x==2] # => [1, 3]

0 votes

J'ai lu beaucoup de pages se plaignant de l'absence de trouver la fonction intégrée for list en python... vous êtes donc d'accord pour dire que (if x in list :) est la façon correcte de faire une recherche dans une liste en python ?

0 votes

@Stephane : Dans quel but ? if x in list vérifiera simplement la présence d'un élément. Si vous voulez réellement "trouver" quelque chose correspondant à un certain critère, vous disposez des expressions de compréhension/générateur de liste, qui sont vraiment puissantes.

0 votes

Dans quel but ? parce que je suis un vieil homme de c++ et je suis coincé avec le concept de trouver des éléments dans des listes dans ma tête... donc je veux être sûr de savoir comment faire cela en python... d'après ce que j'ai lu, j'aime la compréhension des listes, mais elles font des choses quand elles trouvent des choses.

271voto

Janusz Skonieczny Points 1587

Si vous voulez trouver un élément ou None utiliser la valeur par défaut dans next il n'y aura pas d'augmentation StopIteration si l'élément n'a pas été trouvé dans la liste :

first_or_default = next((x for x in lst if ...), None)

2 votes

next prend un itérateur comme premier paramètre et une liste/tuple n'est PAS un itérateur. Cela devrait donc être first_or_default = next(iter([x for x in lst if ...]), None) voir docs.python.org/3/library/functions.html#suivant

21 votes

@Devy : c'est vrai, mais (x for x in lst if ...) est un générateur sur la liste lst (qui est un itérateur). Si vous faites next(iter([x for x in lst if ...]), None) vous devez construire la liste [x for x in lst if ...] qui sera une opération beaucoup plus coûteuse.

2 votes

Il y a une abstraction ici pour définir une fonction de recherche. Il suffit d'encapsuler l'expession booléenne de la fonction if dans un lambda & vous pouvez écrire find(fn,list) généralement au lieu d'obfusquer le code du générateur.

34voto

Vincent Points 1583

Bien que la réponse de Niklas B. soit assez complète, lorsque nous voulons trouver un élément dans une liste, il est parfois utile d'obtenir son index :

next((i for i, x in enumerate(lst) if [condition on x]), [default value])

29voto

Antony Hatchkins Points 5831

Trouver la première occurrence

Il y a une recette pour ça dans itertools :

def first_true(iterable, default=False, pred=None):
    """Returns the first true value in the iterable.

    If no true value is found, returns *default*

    If *pred* is not None, returns the first item
    for which pred(item) is true.

    """
    # first_true([a,b,c], x) --> a or b or c or x
    # first_true([a,b], x, f) --> a if f(a) else b if f(b) else x
    return next(filter(pred, iterable), default)

Par exemple, le code suivant trouve le premier nombre impair dans une liste :

>>> first_true([2,3,4,5], None, lambda x: x%2==1)
3

10voto

Engineero Points 938

Une autre alternative : vous pouvez vérifier si un élément est dans une liste avec if item in list: mais c'est un ordre O(n). Si vous avez affaire à de grandes listes d'éléments et que tout ce dont vous avez besoin est de savoir si un élément est membre de votre liste, vous pouvez d'abord convertir la liste en un ensemble et tirer parti des avantages suivants recherche d'un ensemble de temps constant :

my_set = set(my_list)
if item in my_set:  # much faster on average than using a list
    # do something

Ce ne sera pas la bonne solution dans tous les cas, mais dans certains cas, cela peut vous donner de meilleures performances.

Notez que la création de l'ensemble avec set(my_list) est également O(n), donc si vous n'avez besoin de le faire qu'une seule fois, il n'est pas plus rapide de le faire de cette façon. Par contre, si vous devez vérifier l'appartenance de façon répétée, il faudra utiliser O(1) pour chaque consultation après la création initiale de l'ensemble.

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