2009-05-12 14 views
5

Quiero encontrar la ubicación (es) de un elemento específico en una lista de listas. Debería devolver una lista de tuplas, donde cada tupla representa los índices de una instancia específica del artículo. Por ejemplo:¿Cómo puedo encontrar las ubicaciones de un elemento en una lista de listas de Python?

list = [['1', '2', '4', '6'], ['7', '0', '1', '4']] 
getPosition('1') #returns [(0, 0), (1, 2)] 
and getPosition('7') #returns [(1,0)] 
+0

lo que debe ser devuelto para la siguiente lista: [[ '1', '1', '1', '1'], [ '7', '0', '4'] ]? – SilentGhost

+0

@SilentGhost - Yo diría: [(0,0), (0,1), (0,2), (0,3)] –

+3

Evitaría usar el nombre de variable "lista", ya que esto es un tipo incorporado – Noah

Respuesta

2
def get_positions(xs, target): 
    return [(i,e.index(target)) for i,e in enumerate(xs)] 

Ese es un buen punto de partida. Es de suponer que usted tiene algún tipo de clase como

class SomeClass: 
    def __init__(self): 
     self.xs = [['1','2','4','6'], ['7','0','1','4']] 

    def get_positions(self, target): 
     return [(i,e.index(target)) for i,e in enumerate(self.xs)] 

que en este caso sería dejar que usted dice

model = SomeClass() 
model.get_position(1) # returns [(0,0), (1,2)] 

Nótese que en ambos casos obtendrá una excepción si su objetivo no es en todos una de tus sublistas La pregunta no especifica si este es el comportamiento deseado.

+0

No creo que esto encaje en la pregunta. El argumento para 'getPosition' es un elemento (o subelemento) mientras que el valor devuelto es una posición, no al revés. –

+0

Sí, lo leí mal al principio, pero desde entonces he arreglado mi código para hacer lo correcto. –

5

Parece que desea, para una lista de sublistas y un elemento determinado, devolver una lista de pares donde está cada par (el índice de la sublista, el índice del artículo dentro de la sublista). Puede hacer que el uso de list comprehensions y Python de enumerate() construida en función de: la respuesta @ Ver garabato de arriba/abajo:

def getPosition(list, item): 
    return [(i, sublist.index(item)) for i, sublist in enumerate(list)] 

Editar.

+0

y +1 para el icono ResEdit :) – Noah

+0

Esto se romperá si el artículo no está en cada sublista. Vea mi sugerencia a continuación. O más arriba, eventualmente, espero :-) - scrible 53 secs ago – Arkady

+0

Sí, voy a -1 por el motivo de @ scrible: esto generará una excepción si a una sublista le falta un elemento. –

2

Si no desea una excepción si el artículo no está en la lista, intente esto. También como generador porque son geniales y versátiles.

xs = [['1', '2', '4', '6'], ['7', '0', '1', '4']] 
def get_positions(xs, item): 
    for i, xt in enumerate(xs): 
     try: # trying beats checking 
      yield (i, xt.index(item)) 
     except ValueError: 
      pass 

print list(get_positions(xs, '1')) 
print list(get_positions(xs, '6')) 

# Edit for fun: The one-line version, without try: 

get_positions2 = lambda xs,item: ((i,xt.index(item)) for i, xt in enumerate(xs) if item in xt) 

print list(get_positions2(xs, '1')) 
print list(get_positions2(xs, '6')) 
7

Si quieres algo que a la vez

  • encontrar duplicados y
  • mango listas anidadas (listas de listas de listas de ...)

se puede hacer algo como el siguiente:

def get_positions(xs, item): 
    if isinstance(xs, list): 
     for i, it in enumerate(xs): 
      for pos in get_positions(it, item): 
       yield (i,) + pos 
    elif xs == item: 
     yield() 

Prueba esto:

>>> xs = [['1', '2', '4', '6'], 
...  ['7', '0', '1', '4'], 
...  [ [ '0', '1', '1'], ['1']] 
...  ] 
>>> print list(get_positions(xs, '1')) 
[(0, 0), (1, 2), (2, 0, 1), (2, 0, 2), (2, 1, 0)] 
0

Hace un tiempo escribí una biblioteca de Python para hacer lista de coincidencias que se ajuste a la factura bastante bien. Usó los tokens?, + Y * como comodines, ¿dónde? significa un átomo individual, + es uno o más no codicioso, y * es codicioso uno o más. Por ejemplo:

from matching import match 

match(['?', 2, 3, '*'], [1, 2, 3, 4, 5]) 
=> [1, [4, 5]] 

match([1, 2, 3], [1, 2, 4]) 
=> MatchError: broken at 4 

match([1, [2, 3, '*']], [1, [2, 3, 4]]) 
=> [[4]] 

match([1, [2, 3, '*']], [1, [2, 3, 4]], True) 
=> [1, 2, 3, [4]] 

Descargar aquí: http://www.artfulcode.net/wp-content/uploads/2008/12/matching.zip

0

Aquí es una versión sin tratar ..excepto, volviendo un iterador y que por

[['1', '1', '1', '1'], ['7', '0', '4']] 

vuelve

[(0, 0), (0, 1), (0, 2), (0, 3)] 


def getPosition1(l, val): 
    for row_nb, r in enumerate(l): 
     for col_nb in (x for x in xrange(len(r)) if r[x] == val): 
     yield row_nb, col_nb 
+0

cuenta que la siguiente parece incluso un poco más rápido: def getPosition1 (l, val): para row_nb, r en la enumeración (l): para col_nb, _ en la enumeración (artículo por artículo si el artículo r == val): yield row_nb, col_nb – odwl

0

El más strainghtforward y probablemente la manera más lenta que hacer sería:

>>> value = '1' 
    >>> l = [['1', '2', '3', '4'], ['3', '4', '5', '1']] 
    >>> m = [] 
    >>> for i in range(len(l)): 
    ... for j in range(len(l[i])): 
    ... if l[i][j] == value: 
    ... m.append((i,j)) 
    ... 
    >>> m 
    [(0, 0), (1, 3)] 
0

Aquí hay otro método directo y que no usa generadores

def getPosition(lists,item): 
    positions = [] 
    for i,li in enumerate(lists): 
     j = -1 
     try: 
      while True: 
       j = li.index(item,j+1) 
       positions.append((i,j)) 
     except ValueError: 
      pass 
    return positions 

l = [['1', '2', '4', '6'], ['7', '0', '1', '4']] 
getPosition(l,'1') #returns [(0, 0), (1, 2)] 
getPosition(l,'9') # returns [] 

l = [['1', '1', '1', '1'], ['7', '0', '1', '4']] 
getPosition(l,'1') #returns [(0, 0), (0, 1), (0,2), (0,3), (1,2)] 
3
def getPosition(list, item): 
    return [(i, sublist.index(item)) for i, sublist in enumerate(list) 
                 if item in sublist] 
+1

parece que garabatos o scrible ha cambiado de nombre? De lo contrario, ¿a quién se refiere @apaidnerd? – emmagras

Cuestiones relacionadas