Pregunta

El tipo de lista de Python tiene un método index() que toma un parámetro y devuelve el índice del primer elemento de la lista que coincide con el parámetro.Por ejemplo:

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

¿Existe una forma elegante (idiomática) de extender esto a listas de objetos complejos, como tuplas?Idealmente, me gustaría poder hacer algo como esto:

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

getIndexOfTuple() es solo un método hipotético que acepta un subíndice y un valor, y luego devuelve el índice del elemento de la lista con el valor dado en ese subíndice.Espero

¿Hay alguna manera de lograr ese resultado general, utilizando listas por comprensión o lambas o algo "en línea" como eso?Creo que podría escribir mi propia clase y método, pero no quiero reinventar la rueda si Python ya tiene una manera de hacerlo.

¿Fue útil?

Solución

¿Qué tal esto?

>>> 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]

Como se ha señalado en los comentarios, esto sería conseguir todos los partidos. Para obtener sólo la primera, que puede hacer:

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

Hay una buena discusión en los comentarios en cuanto a la diferencia de velocidad entre todas las soluciones publicadas. Puede que sea un poco parcial pero me gustaría seguir personalmente a una sola línea como la velocidad que estamos hablando es bastante insignificante en comparación con la creación de funciones y la importación de módulos para este problema, pero si usted está planeando en hacer esto a una cantidad muy grande de elementos es posible que desee mirar a las otras respuestas proporcionadas, ya que son más rápido que lo que he proporcionado.

Otros consejos

Estas listas por comprensión son sucios después de un tiempo.

Me gusta este enfoque 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 se necesita el código para ser todo súper 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

Una posibilidad es utilizar la función de itemgetter desde el módulo operator :

import operator

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

La llamada a itemgetter devuelve una función que hará el equivalente a foo[0] para cualquier cosa que se le pasa. Usando map, a continuación, aplica esa función a cada tupla, la extracción de la información en una nueva lista, en la que a continuación, llama index de forma normal.

map(f, tuple_list)

es equivalente a:

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

que a su vez es equivalente a:

[tuple_list[0][0], tuple_list[1][0], tuple_list[2][0]]

lo que da:

["pineapple", "cherry", ...etc]

Puede hacer esto con una lista por comprensión y el índice ()

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

Yo pondría esto como un comentario a Tríptico, pero no puedo comentar sin embargo, debido a la falta de calificación:

Utilizando el método empadronador para que coincida con el sub-índices en una lista de tuplas. por ejemplo.

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

Inspirado por esta pregunta, encontré esto bastante elegante:

>>> 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

bien, podría ser un error en vals(j), la corrección es:

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
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)
z = list(zip(*tuple_list))
z[1][z[0].index('persimon')]

No se sugiere cuerpo lambdas?

Y probar esto y obras. Vengo a esta respuesta posterior búsqueda. No me di cuenta de que me gusta, pero me siento un insingth: P

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

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

Editar para añadir ejemplos:

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

extraer todos los artículos por condiciones:         filtro (lambda x: x [0] == "pato", l) # [[ 'pato', 2, 1], [ 'pato', 2, 2], [ 'pato', 2, 2]]

extraer todos los artículos por condiciones, con índice:

    >>> 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]]

Nota: _ variable sólo funciona en archivo de texto normal y intérprete interactivo _ necesitar explicti asignar, es decir, _ = filtrado (lambda x: x [1] [0] == "pato", enumerar (l))

list.index de Python (x) devuelve el índice de la primera ocurrencia de x en la lista. Así que podemos pasar objetos devueltos por la compresión lista para obtener su índice.

>>> 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]

Con la misma línea, también podemos obtener la lista de índice en caso de que haya varios elementos coincidentes.

>>> 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]

Creo que los siguientes no es la mejor manera de hacerlo (de velocidad y elegancia preocupaciones), pero bueno, podría ayudar a:

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

lista de tuplas con 2 miembros se puede convertir en dict pedir directamente, estructuras de datos son en realidad la misma, por lo que puede utilizar el método dict sobre la marcha.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top