2010-01-11 9 views
9

Tengo el siguiente código:Una forma más de Pythonic se repite una lista mientras se excluye un elemento cada iteración

items = ["one", "two", "three"] 

for i in range(0, len(items)): 
    for index, element in enumerate(items): 
     if index != i: 
      # do something with element 

Básicamente quiero excluir todos los elementos de una vez y repetir el resto. Así que para la lista que tengo encima, me gustaría que las siguientes iteraciones:

  1. "dos", "tres"
  2. "uno", "tres"
  3. "uno", "dos"

El código que he escrito ahora parece un poco C++ - ish, ¿hay una solución mejor? (No quiero mantener todas las listas posibles en una variable)

EDITAR: No dije esto pero el tamaño de las listas no es necesariamente 3. Puede ser de cualquier tamaño.

EDIT 2: Parece que hay otro malentendido: si tengo una lista de N, entonces quiero N listas de tamaño N-1, cada una falta un elemento de la lista original.

EDITAR 3: Una lista con 4 elementos, debe dar a este resultado:

  1. 1, 2, 3
  2. 1, 3, 4
  3. 1, 2, 4
  4. 2, 3, 4
+6

Predigo obtendrá una docena de respuestas a este, 'itertools 'y se invocarán las comprensiones del generador, pero al final no se propondrá nada mejor que su código inicial. –

+0

Nah, podría haber usado 'xrange (len (items))'. – Tobu

+0

Nah, él ya está usando Python 3 :) –

Respuesta

17

Aunque upvoted como un loco, mi primera solución no era lo que quería el OP, que es N listas, cada una falta exactamente uno de los elementos originales N:

>>> from itertools import combinations 
>>> L = ["one", "two", "three", "four"] 
>>> for R in combinations(L, len(L) - 1): 
...  print " and ".join(R) 
... 
one and two and three 
one and two and four 
one and three and four 
two and three and four 

Véase el revision history para la fuente de la discusión que sigue.

+1

Pero la lista que había escrito era solo un ejemplo. En la práctica puede ser de talla N. – roger

+0

Esto es mucho más explícito y claro que el código inicial, ¿entonces creo que califica como mejor? Por lo menos, esto es más pitónico. – donut

+5

en realidad no, quiero iterar todas las "combinaciones" de longitud 'N-1'. – roger

5
[items[:i]+items[i+1:] for i in range(len(items))] 

en uso py2.x xrange. obviamente, rebanar todo el tiempo en una gran secuencia no es muy eficiente, pero está bien para los cortos. Una mejor opción sería utilizar itertools.combinations:

>>> for a in itertools.combinations(items, len(items)-1): 
    print(a) 

('one', 'two') 
('one', 'three') 
('two', 'three') 
1

Como se predijo Roger, una respuesta que en realidad no mejorar el código existente :)

a = ["one", "two", "three"] 
for i in range(0, len(a)): 
    print [val[1] for val in enumerate(a) if val[0] != i] 
Cuestiones relacionadas