web-dev-qa-db-fra.com

Vous utilisez la méthode list index () de Python sur une liste de n-uplets ou d'objets?

Le type de liste de Python a une méthode index () qui prend un paramètre et retourne l'index du premier élément de la liste correspondant au paramètre. Par exemple:

>>> some_list = ["Apple", "pear", "banana", "grape"]
>>> some_list.index("pear")
1
>>> some_list.index("grape")
3

Existe-t-il un moyen gracieux (idiomatique) d’étendre cela aux listes d’objets complexes, comme des n-uplets? Idéalement, j'aimerais pouvoir faire quelque chose comme ceci:

>>> Tuple_list = [("pineapple", 5), ("cherry", 7), ("kumquat", 3), ("Plum", 11)]
>>> some_list.getIndexOfTuple(1, 7)
1
>>> some_list.getIndexOfTuple(0, "kumquat")
2

getIndexOfTuple () est simplement une méthode hypothétique qui accepte un sous-index et une valeur, puis renvoie l'index de l'élément de liste avec la valeur donnée au niveau de ce sous-index. J'espère

Existe-t-il un moyen d'obtenir ce résultat général en utilisant des listes de compréhension ou des lambas ou quelque chose comme "en ligne"? Je pense que je pourrais écrire ma propre classe et méthode, mais je ne veux pas réinventer la roue si Python a déjà un moyen de le faire.

45
Ryan B. Lynch

Que dis-tu de ça?

>>> Tuple_list = [("pineapple", 5), ("cherry", 7), ("kumquat", 3), ("Plum", 11)]
>>> [x for x, y in enumerate(Tuple_list) if y[1] == 7]
[1]
>>> [x for x, y in enumerate(Tuple_list) if y[0] == 'kumquat']
[2]

Comme indiqué dans les commentaires, tous les matchs seraient obtenus. Pour obtenir le premier, vous pouvez faire:

>>> [y[0] for y in Tuple_list].index('kumquat')
2

Il y a une bonne discussion dans les commentaires sur la différence de vitesse entre toutes les solutions affichées. Je suis peut-être un peu partial, mais personnellement, je préfère m'en tenir à une ligne car la vitesse dont nous parlons est plutôt insignifiante par rapport à la création de fonctions et à l'importation de modules pour ce problème, vous voudrez peut-être examiner les autres réponses fournies, car elles sont plus rapides que ce que j’ai fourni.

59
Paolo Bergantino

Ces compréhensions de liste sont en désordre après un certain temps.

J'aime cette approche Pythonic:

from operator import itemgetter

def collect(l, index):
   return map(itemgetter(index), l)

# And now you can write this:
collect(Tuple_list,0).index("cherry")   # = 1
collect(Tuple_list,1).index("3")        # = 2

Si vous avez besoin que votre code soit tout à fait performant:

# Stops iterating through the list as soon as it finds the value
def getIndexOfTuple(l, index, value):
    for pos,t in enumerate(l):
        if t[index] == value:
            return pos

    # Matches behavior of list.index
    raise ValueError("list.index(x): x not in list")

getIndexOfTuple(Tuple_list, 0, "cherry")   # = 1
26
Triptych

Une possibilité consiste à utiliser la fonction itemgetter du module operator:

import operator

f = operator.itemgetter(0)
print map(f, Tuple_list).index("cherry") # yields 1

L'appel à itemgetter renvoie une fonction qui fera l'équivalent de foo[0] pour tout ce qui lui est transmis. En utilisant map, vous appliquez ensuite cette fonction à chaque tuple en extrayant les informations dans une nouvelle liste, sur laquelle vous appelez ensuite index normalement.

map(f, Tuple_list)

est équivalent à:

[f(Tuple_list[0]), f(Tuple_list[1]), ...etc]

ce qui équivaut à:

[Tuple_list[0][0], Tuple_list[1][0], Tuple_list[2][0]]

qui donne:

["pineapple", "cherry", ...etc]
9
Jarret Hardie

Vous pouvez le faire avec une compréhension de liste et un index ()

Tuple_list = [("pineapple", 5), ("cherry", 7), ("kumquat", 3), ("Plum", 11)]
[x[0] for x in Tuple_list].index("kumquat")
2
[x[1] for x in Tuple_list].index(7)
1
5
Alasdair

Je placerais ceci comme un commentaire à Triptych, mais je ne peux pas encore commenter à cause du manque d'évaluation

Utilisation de la méthode énumératrice pour établir une correspondance sur des sous-indices dans une liste de tuples.

li = [(1,2,3,4), (11,22,33,44), (111,222,333,444), ('a','b','c','d'),
        ('aa','bb','cc','dd'), ('aaa','bbb','ccc','ddd')]

# want pos of item having [22,44] in positions 1 and 3:

def getIndexOfTupleWithIndices(li, indices, vals):

    # if index is a Tuple of subindices to match against:
    for pos,k in enumerate(li):
        match = True
        for i in indices:
            if k[i] != vals[i]:
                match = False
                break;
        if (match):
            return pos

    # Matches behavior of list.index
    raise ValueError("list.index(x): x not in list")

idx = [1,3]
vals = [22,44]
print getIndexOfTupleWithIndices(li,idx,vals)    # = 1
idx = [0,1]
vals = ['a','b']
print getIndexOfTupleWithIndices(li,idx,vals)    # = 3
idx = [2,1]
vals = ['cc','bb']
print getIndexOfTupleWithIndices(li,idx,vals)    # = 4
2
Nisan.H

Inspiré par cette question , j'ai trouvé cela assez élégant:

>>> Tuple_list = [("pineapple", 5), ("cherry", 7), ("kumquat", 3), ("Plum", 11)]
>>> next(i for i, t in enumerate(Tuple_list) if t[1] == 7)
1
>>> next(i for i, t in enumerate(Tuple_list) if t[0] == "kumquat")
2
2
Claudiu

ok, cela pourrait être une erreur dans vals(j), la correction est:

def getIndex(li,indices,vals):
for pos,k in enumerate(lista):
    match = True
    for i in indices:
        if k[i] != vals[indices.index(i)]:
            match = False
            break
    if(match):
        return pos
1
dulce ambrocio
Tuple_list = [("pineapple", 5), ("cherry", 7), ("kumquat", 3), ("Plum", 11)]

def eachtuple(tupple, pos1, val):
    for e in tupple:
        if e == val:
            return True

for e in Tuple_list:
    if eachtuple(e, 1, 7) is True:
        print Tuple_list.index(e)

for e in Tuple_list:
    if eachtuple(e, 0, "kumquat") is True:
        print Tuple_list.index(e)
1
Ricardo Trujillo

Je suppose que ce qui suit n’est pas la meilleure façon de le faire (problèmes de vitesse et d’élégance), mais bon, cela pourrait aider: 

from collections import OrderedDict as od
t = [('pineapple', 5), ('cherry', 7), ('kumquat', 3), ('Plum', 11)]
list(od(t).keys()).index('kumquat')
2
list(od(t).values()).index(7)
7
# bonus :
od(t)['kumquat']
3

la liste des tuples avec 2 membres peut être convertie en dict ordonné directement, les structures de données sont en fait les mêmes, nous pouvons donc utiliser la méthode dict à la volée.

0
jerome

Le fichier list.index (x) de Python renvoie l'index de la première occurrence de x dans la liste. Nous pouvons donc passer les objets retournés par compression de liste pour obtenir leur index.

>>> Tuple_list = [("pineapple", 5), ("cherry", 7), ("kumquat", 3), ("Plum", 11)]
>>> [Tuple_list.index(t) for t in Tuple_list if t[1] == 7]
[1]
>>> [Tuple_list.index(t) for t in Tuple_list if t[0] == 'kumquat']
[2]

Avec la même ligne, nous pouvons également obtenir la liste des index au cas où il y aurait plusieurs éléments correspondants.

>>> Tuple_list = [("pineapple", 5), ("cherry", 7), ("kumquat", 3), ("Plum", 11), ("banana", 7)]
>>> [Tuple_list.index(t) for t in Tuple_list if t[1] == 7]
[1, 4]
0
dspmeng
z = list(Zip(*Tuple_list))
z[1][z[0].index('persimon')]
0
eyaler

Aucun corps ne suggère de lambdas?

Y essayez ceci et fonctionne. Je viens à cette réponse de recherche post. Je n'ai pas trouvé que j'aimais, mais je me sens insingth: P

    l #[['rana', 1, 1], ['pato', 1, 1], ['perro', 1, 1]]

    map(lambda x:x[0], l).index("pato") #1 

Modifier pour ajouter des exemples: 

   l=[['rana', 1, 1], ['pato', 2, 1], ['perro', 1, 1], ['pato', 2, 2], ['pato', 2, 2]]

extraire tous les articles par condition: filtre (lambda x: x [0] == "pato", l) # [['pato', 2, 1], ['pato', 2, 2], ['pato', 2, 2]]

extraire tous les articles par condition avec index:

    >>> filter(lambda x:x[1][0]=="pato", enumerate(l))
    [(1, ['pato', 2, 1]), (3, ['pato', 2, 2]), (4, ['pato', 2, 2])]
    >>> map(lambda x:x[1],_)
    [['pato', 2, 1], ['pato', 2, 2], ['pato', 2, 2]]

Remarque: la variable _ ne fonctionne que dans l'interpréteur interactif y fichier de texte normal

0
Wallebot