W Pythonie, jak zrobić coś takiego:
for car in cars:
# Skip first and last, do work for rest
Pozostałe odpowiedzi działają tylko dla sekwencji.
W przypadku dowolnej iteracji pomiń pierwszy element:
itercars = iter(cars)
next(itercars)
for car in itercars:
# do work
Jeśli chcesz pominąć ostatni, możesz:
itercars = iter(cars)
# add 'next(itercars)' here if you also want to skip the first
prev = next(itercars)
for car in itercars:
# do work on 'prev' not 'car'
# at end of loop:
prev = car
# now you can do whatever you want to do to the last one on 'prev'
Aby pominąć pierwszy element w Pythonie, możesz po prostu napisać
for car in cars[1:]:
# Do What Ever you want
lub pominąć ostatni elem
for car in cars[:-1]:
# Do What Ever you want
Możesz użyć tej koncepcji do dowolnej sekwencji.
Najlepszym sposobem na pominięcie pierwszych elementów jest:
from itertools import islice
for car in islice(cars, 1, None):
# do something
islice w tym przypadku jest wywoływane z punktem początkowym 1 i punktem końcowym Brak, co oznacza koniec iteratora.
Aby móc pominąć elementy z końca iteracji, musisz znać jego długość (zawsze jest to możliwe dla listy, ale niekoniecznie dla wszystkiego, co możesz iterować). na przykład islice (samochody, 1, len (samochody) -1) pomija pierwszy i ostatni element na liście samochodów.
islice
całkiem dobrze, bez znajomości długości lub przechowywania większej liczby przedmiotów na raz, niż jest to absolutnie konieczne.
islice
Jest to, co jest przekazywane do deque
, a nie całego iterator, i to tylko długość liczby elementów, aby przejść na koniec. Nie przechowuje całego iteratora w pamięci.
Oto bardziej ogólna funkcja generatora, która pomija dowolną liczbę elementów od początku i końca iteracji:
def skip(iterable, at_start=0, at_end=0):
it = iter(iterable)
for x in itertools.islice(it, at_start):
pass
queue = collections.deque(itertools.islice(it, at_end))
for x in it:
queue.append(x)
yield queue.popleft()
Przykładowe użycie:
>>> list(skip(range(10), at_start=2, at_end=2))
[2, 3, 4, 5, 6, 7]
at_end == 0
.
skip(xrange(10000000), 1)
użyje at_end=0
, więc parametrem deque()
będzie islice(it, 0)
, który będzie zużywał tylko zero elementów it
. To nie zajmie dużo pamięci.
for item in do_not_use_list_as_a_name[1:-1]:
#...do whatever
list
jako nazwy zmiennej
list
może zostać ponownie powiązana. Dlatego nie powinien , raczej niż nie , użyj go.
Na podstawie odpowiedzi @ SvenaMarnacha, ale nieco prostsze i bez użycia deque
>>> def skip(iterable, at_start=0, at_end=0):
it = iter(iterable)
it = itertools.islice(it, at_start, None)
it, it1 = itertools.tee(it)
it1 = itertools.islice(it1, at_end, None)
return (next(it) for _ in it1)
>>> list(skip(range(10), at_start=2, at_end=2))
[2, 3, 4, 5, 6, 7]
>>> list(skip(range(10), at_start=2, at_end=5))
[2, 3, 4]
Również uwaga, w oparciu o mój timeit
wynik, jest to nieznacznie szybsze niż rozwiązanie deque
>>> iterable=xrange(1000)
>>> stmt1="""
def skip(iterable, at_start=0, at_end=0):
it = iter(iterable)
it = itertools.islice(it, at_start, None)
it, it1 = itertools.tee(it)
it1 = itertools.islice(it1, at_end, None)
return (next(it) for _ in it1)
list(skip(iterable,2,2))
"""
>>> stmt2="""
def skip(iterable, at_start=0, at_end=0):
it = iter(iterable)
for x in itertools.islice(it, at_start):
pass
queue = collections.deque(itertools.islice(it, at_end))
for x in it:
queue.append(x)
yield queue.popleft()
list(skip(iterable,2,2))
"""
>>> timeit.timeit(stmt = stmt1, setup='from __main__ import iterable, skip, itertools', number = 10000)
2.0313770640908047
>>> timeit.timeit(stmt = stmt2, setup='from __main__ import iterable, skip, itertools, collections', number = 10000)
2.9903135454296716
tee()
, nadal tworzysz całą listę pamięci generatora, prawda? (twój it1
)
Przykład:
mylist=['one'.'two','three'.'four'.'five']
for i in mylist[1:]:
print(i)
W indeksie pythonowym zaczynającym się od 0, możemy używać operatora krojenia, aby manipulować iteracją.
for i in range(1,-1):
Cóż, twoja składnia nie jest tak naprawdę Pythonem.
Iteracje w Pythonie są ponad zawartością kontenerów (cóż, technicznie jest to ponad iteratorami), ze składnią for item in container
. W tym przypadku kontener jest cars
listą, ale chcesz pominąć pierwszy i ostatni element, co oznacza cars[1:-1]
(listy python są liczone od zera, liczby ujemne liczą się od końca i :
kroi składnię.
Więc chcesz
for c in cars[1:-1]:
do something with c
Alternatywna metoda:
for idx, car in enumerate(cars):
# Skip first line.
if not idx:
continue
# Skip last line.
if idx + 1 == len(cars):
continue
# Real code here.
print car
Oto mój preferowany wybór. Nie wymaga dodawania wiele do pętli i używa tylko wbudowanych narzędzi.
Przejdź od:
for item in my_items:
do_something(item)
do:
for i, item in enumerate(my_items):
if i == 0:
continue
do_something(item)
Jeśli cars
jest to sekwencja, którą możesz po prostu zrobić
for car in cars[1:-1]:
pass
The more_itertools
Projekt rozszerzaitertools.islice
obsłużyć ujemnych indeksów.
Przykład
import more_itertools as mit
iterable = 'ABCDEFGH'
list(mit.islice_extended(iterable, 1, -1))
# Out: ['B', 'C', 'D', 'E', 'F', 'G']
Dlatego możesz elegancko zastosować elementy do wycinania między pierwszym a ostatnim elementem iteracji:
for car in mit.islice_extended(cars, 1, -1):
# do something
Robię to w ten sposób, mimo że wygląda to na hack, działa za każdym razem:
ls_of_things = ['apple', 'car', 'truck', 'bike', 'banana']
first = 0
last = len(ls_of_things)
for items in ls_of_things:
if first == 0
first = first + 1
pass
elif first == last - 1:
break
else:
do_stuff
first = first + 1
pass
for n, i in enumerate(cars): if n!= 0: do something to i
. logika polega na tym, że dodaje „licznik” do każdej wartości, którą można następnie celować npif n == some_value
. za pomocą . w tym przykładzie zrobiłby coś dla każdego wystąpienia i, z wyjątkiem pierwszego.