Pergunta

tipo de lista do Python tem um método index () que recebe um parâmetro e retorna o índice do primeiro item na lista corresponde ao parâmetro. Por exemplo:

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

Existe uma maneira graciosa (idiomática) para estender isso para listas de objetos complexos, como tuplas? Idealmente, eu gostaria de ser capaz de fazer algo parecido com isto:

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

getIndexOfTuple () é apenas um método hipotético que aceita um sub-índice e um valor e, em seguida, retorna o índice do item da lista com o valor dado naquela sub-índice. Espero

Existe alguma maneira de alcançar esse resultado geral, usando compreensões de lista ou Lambas ou algo assim "in-line" como esse? Eu acho que eu poderia escrever minha própria classe e método, mas eu não quero reinventar a roda se Python já tem uma maneira de fazê-lo.

Foi útil?

Solução

Como sobre isso?

>>> 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 apontado nos comentários, este iria receber todos os jogos. Para obter apenas o primeiro, você pode fazer:

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

Há uma boa discussão nos comentários sobre a diferença de velocidade entre todas as soluções postadas. I pode ser um pouco tendenciosa, mas eu pessoalmente ficar com uma frase como a velocidade que estamos falando é muito insignificante em relação a criação de funções e importação de módulos para este problema, mas se você está pensando em fazer isso para uma quantidade muito grande de elementos que você pode querer olhar para as outras respostas fornecidas, como eles são mais rápidos do que o que eu forneci.

Outras dicas

Essas compreensões lista são desorganizados depois de um tempo.

Eu gosto desta abordagem 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

Se você precisa de seu código para ser todos super performance:

# 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

Uma possibilidade é usar a função itemgetter do módulo operator :

import operator

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

A chamada para itemgetter retorna uma função que irá fazer o equivalente a foo[0] para qualquer coisa passada para ele. Usando map, em seguida, aplicar essa função para cada tupla, extraindo a informação em uma nova lista, na qual você então chamar index como normal.

map(f, tuple_list)

é equivalente a:

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

que por sua vez é equivalente a:

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

que dá:

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

Você pode fazer isso com uma compreensão lista e 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

Eu colocaria isso como um comentário a Tríptico, mas eu não posso comentar ainda devido à falta de classificação:

Usando o método enumerador para corresponder em sub-índices em uma lista de tuplas. por exemplo.

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

ok, pode ser um erro na vals(j), a correção é:

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 corpo sugerem lambdas?

Y tentar isso e obras. Venho a esta resposta pós busca. Eu não achei que eu gosto, mas eu me sinto um insingth: P

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

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

Editar para adicionar exemplos:

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

extrair todos os itens de condição: filtro (lambda X: X [0] == "pato", l) # [[ 'pato', 2, 1], [ 'pato', 2, 2], [ 'pato', 2, 2]]

extrair todos os itens de condição com o í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: _ variável só funciona em interativo intérprete y arquivo de texto normal _ necessidade explicti atribuir, ou seja _ = filtro (lambda x: x [1] [0] == "pato", enumerate (l))

list.index do Python (x) retorna o índice da primeira ocorrência de x na lista. Assim, podemos passar objetos retornados por compressão lista para obter seu í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]

Com a mesma linha, podemos também obter a lista de índice no caso de existirem vários elementos combinados.

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

Eu acho o seguinte não é a melhor maneira de fazer isso (velocidade e elegância preocupações), mas bem, poderia ajudar:

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 com 2 membros pode ser convertido para dict encomendados diretamente, estruturas de dados são realmente a mesma, para que possamos utilizar dict método on the fly.

scroll top