una - metodos de listas en python
¿Usando el método de índice de la lista de Python() en una lista de tuplas u objetos? (12)
El tipo de lista de Python tiene un método de índice () que toma un parámetro y devuelve el índice del primer elemento en 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, usando listas de comprensión o lambas o algo "en línea" como ese? Creo que podría escribir mi propia clase y método, pero no quiero reinventar la rueda si Python ya tiene una forma de hacerlo.
¿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 señaló en los comentarios, esto obtendría todas las coincidencias. Para obtener el primero, puede hacer:
>>> [y[0] for y in tuple_list].index(''kumquat'')
2
Hay una buena discusión en los comentarios sobre la diferencia de velocidad entre todas las soluciones publicadas. Puede que sea un poco parcial, pero me apegaré personalmente a una sola línea, ya que la velocidad a la que nos referimos es bastante insignificante versus la creación de funciones y la importación de módulos para este problema, pero si estás planeando hacerlo en una cantidad muy grande de elementos es posible que desee ver las otras respuestas proporcionadas, ya que son más rápidos que lo que proporcioné.
Colocaría esto como un comentario en Triptych, pero aún no puedo comentar debido a la falta de calificación:
Usar el método del enumerador para hacer coincidir los subíndices en una lista de tuplas. p.ej
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
Esas listas de comprensión son desordenadas 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 necesita que su código sea todo superperformance:
# 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
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
Ningún cuerpo sugiere lambdas?
Y prueba esto y funciona. Vengo a esta respuesta de búsqueda posterior. No encuentro que me guste, pero siento una insinuación: P
l #[[''rana'', 1, 1], [''pato'', 1, 1], [''perro'', 1, 1]]
map(lambda x:x[0], l).index("pato") #1
Editar para agregar ejemplos:
l=[[''rana'', 1, 1], [''pato'', 2, 1], [''perro'', 1, 1], [''pato'', 2, 2], [''pato'', 2, 2]]
extraer todos los elementos por condición: filter (lambda x: x [0] == "pato", l) # [[''pato'', 2, 1], [''pato'', 2, 2], [''pato'', 2, 2]]
extraer todos los elementos por condición 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: _ la variable solo funciona en intérprete interactivo y el archivo de texto normal _ necesita explicti assign, es decir _ = filter (lambda x: x [1] [0] == "pato", enumerate (l))
Puedes hacer esto con una lista de comprensión e í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
Python''s list.index (x) devuelve el índice de la primera aparición de x en la lista. Entonces podemos pasar objetos devueltos por compresión de 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 múltiples 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]
Supongo que la siguiente no es la mejor manera de hacerlo (cuestiones de velocidad y elegancia) pero bueno, podría ayudar:
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 lista de tuplas con 2 miembros se puede convertir a dict ordenado directamente, las estructuras de datos son en realidad las mismas, por lo que podemos usar el método dict sobre la marcha.
Una posibilidad es usar la función itemgetter del módulo de 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 de foo[0]
para cualquier cosa que se le pase. Usando el map
, entonces aplica esa función a cada tupla, extrayendo la información en una nueva lista, en la que luego llamas al index
como lo haces normalmente.
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]
ok, 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'')]