2016-07-07 9 views

Odpowiedz

38

Cleaner podejście pythonowy:

>>> [(x,y) for x,y in zip(myList, myList[1:]) if y == 9] 
[(8, 9), (4, 9), (7, 9)] 

Co to jest kod powyżej robi:

  • zip(some_list, some_list[1:]) by wygenerować listę par sąsiednich elementów.
  • Teraz z tą krotką filtruj pod warunkiem, że drugi element jest równy 9. Skończysz :)
7

Byłaś całkiem blisko, pokażę ci alternatywny sposób, że może być bardziej intuicyjna, jeśli dopiero zaczynasz:

sets = [(myList[i-1], myList[i]) for i in range(len(myList)) if myList[i] == 9] 

Zdobądź indeks w zakres długości listy, a jeśli wartość na pozycji i jest równa 9, chwyć sąsiednie elementy.

Wynikiem jest:

sets 
[(8, 9), (4, 9), (7, 9)] 

To mniej wydajny niż inne podejścia ale postanowiłem un-go usunąć, aby pokazać inny sposób to robić. Można zrobić to iść nieco szybciej za pomocą enumerate() zamiast:

sets = [(myList[i-1], j) for i, j in enumerate(myList) if j == 9] 

biorą pod uwagę że w przypadku krawędzi gdzie myList[0] = 9 zachowanie pojmowania bez zip i zachowanie zrozumienie z zip jest różne.

szczególności, jeśli myList = [9, 1, 8, 9, 2, 4, 9, 6, 7, 9, 8] następnie:

[(myList[i-1], myList[i]) for i in range(len(myList)) if myList[i] == 9] 
# results in: [(8, 9), (8, 9), (4, 9), (7, 9)] 

natomiast:

[(x, y) for x, y in zip(myList, myList[1:]) if y==9] 
# results in: [(8, 9), (4, 9), (7, 9)] 

To do ciebie, aby zdecydować, który z nich pasuje do Twoich kryteriów, jestem po prostu wskazując, że don” t zachowują się tak samo we wszystkich przypadkach.

17

Częścią twojego problemu jest to, że myList[i:i] zawsze zwróci pustą listę. Koniec plasterek jest wyłączna, więc kiedy robisz a_list[0:0] starasz się wziąć elementy a_list które istnieją między indeksu 0 i indeksu 0.

Jesteś na dobrej drodze, ale chcesz spakuj listę samodzielnie.

[(x, y) for x, y in zip(myList, myList[1:]) if y==9] 
+0

pełni identyczną do mojej odpowiedzi :) – SuperSaiyan

+7

@SuperSaiyan wyjątkiem tego, że twój nie wspomina główny problem PO miał ich użytkowania z 'myList [i: i]'. –

+0

Powiązane lektury dla OP [Wyjaśnij notację plasterka Pythona] (http://stackoverflow.com/q/509211) –

5

Można też zrobić to bez krojenia poprzez tworzenie iteratorów:

l = myList = [1,8,9,2,4,9,6,7,9,8] 

it1, it2 = iter(l), iter(l) 
# consume first element from it2 -> leaving 8,9,2,4,9,6,7,9,8 
next(it2, "") 
# then pair up, (1,8), (8,9) ... 
print([(i, j) for i,j in zip(it1, it2) if j == 9]) 

Albo użyć pairwise recipe do tworzenia par

from itertools import tee, izip 

def pairwise(iterable): 
    "s -> (s0,s1), (s1,s2), (s2, s3), ..." 
    a, b = tee(iterable) 
    next(b, None) 
    return izip(a, b) 

przypadku korzystania python3, tylko importować tee i użyj zwykłego zip.

+0

nie jest już lista iterable, dlaczego iter (l), iter (l)? –

+0

@Phillip, kiedy spożyjesz część iteratora, tj. Następną (it2), przejdziesz do następnego elementu, a pierwszy zostanie zużyty, więc w tym przykładzie zaczynamy od drugiego elementu it2, kiedy zapinamy suwak –

5

To naprawdę zaskakujące, że nikt nie dodał funkcjonalnego podejścia.

Inną alternatywną odpowiedzią jest użycie filter. Ten wbudowany zwraca iterację (lista w python2) zawierającą wszystkie elementy znajdujące się na liście, które zwracają True do konkretnej funkcji

>>> myList = [1,8,9,2,4,9,6,7,9,8] 
>>> list(filter(lambda x:x[1]==9,zip(myList, myList[1:]))) 
[(8, 9), (4, 9), (7, 9)] 

Należy zauważyć, że list call is needed only in python3+. Różnica między podejściem funkcjonalnym a rozumieniem listy jest omówiona w detail in this post.

1

Moje rozwiązanie jest podobny do jednego z Jim zaawansowany z kontrolą zerowego indeksu

myList = [9, 1, 8, 9, 2, 4, 9, 6, 7, 9, 8] 

[(myList[i-1], x) for i, x in enumerate(myList) if x==9 and i!=0] 

# [(8, 9), (4, 9), (7, 9)] 
Powiązane problemy