2010-01-11 13 views
9

Mam następujący kod:bardziej pythonic sposób iteracji listę wykluczając element każdej iteracji

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

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

Zasadniczo chcę wykluczyć każdego elementu raz iteracyjne resztę. Tak na liście mam powyżej, chciałbym następujące iteracji:

  1. „dwa”, „trzy”
  2. „jeden”, „trzy”
  3. „jeden”, „dwa”

Kod, który napisałem, wydaje się być małym C++ - czy jest lepsze rozwiązanie? (Nie chcę przechowywać wszystkich możliwych list w zmiennej)

EDYCJA: Nie podałem tego, ale rozmiar listy niekoniecznie musi być 3. Może być dowolnego rozmiaru.

EDYCJA 2: Wydaje się, że jest jeszcze jedno nieporozumienie: jeśli mam listę N, to potrzebuję N list o rozmiarze N-1, z których każdy nie ma elementu z oryginalnej listy.

Edycja 3: Lista w 4 pozycji, powinno dać ten wynik:

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

Przewiduję dostaniesz kilkanaście odpowiedzi na to, 'itertools Wywołania 'i generatora będą wywoływane, ale na końcu nie zaproponujemy niczego lepszego niż początkowy kod. –

+0

Nie, mógł użyć 'xrange (len (items))'. – Tobu

+0

Nie, on już używa Pythona 3 :) –

Odpowiedz

17

Mimo, że zostałem zaszokowany jak szalony, moje pierwsze rozwiązanie nie było tym, czego potrzebował OP, który jest N listami, z których każdy zawiera dokładnie jeden z N oryginalnych elementów:

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

Zobacz revision history dla źródła dyskusji poniżej.

+1

Ale lista, którą napisałem, była tylko przykładem. W praktyce może mieć rozmiar N. – roger

+0

To jest dużo bardziej wyraźne i jasne niż początkowy kod, więc myślę, że kwalifikuje się jako lepsze? Przynajmniej jest to bardziej pythonic. – donut

+5

właściwie nie, chcę powtórzyć wszystkie "kombinacje" długości "N-1". – roger

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

w py2.x użycie xrange. oczywiście, krojenie cały czas na dużej sekwencji nie jest zbyt wydajne, ale w przypadku krótkich jest w porządku. Lepszym rozwiązaniem byłoby przy użyciu itertools.combinations:

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

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

Zgodnie z przewidywaniami Roger, odpowiedź, która nie naprawdę poprawy istniejącego kodu :)

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