Lewati entri pertama untuk loop dalam python?

187

Dengan python, Bagaimana saya melakukan sesuatu seperti:

for car in cars:
   # Skip first and last, do work for rest
Rolando
sumber
4
Saya seorang pemula, tetapi saya telah menggunakan for n, i in enumerate(cars): if n!= 0: do something to i. Logikanya adalah bahwa ia menambahkan 'penghitung' untuk setiap nilai yang kemudian dapat Anda targetkan misalnya if n == some_value. dalam contoh ini akan melakukan sesuatu untuk setiap instance dari saya, kecuali untuk yang pertama.
user1063287

Jawaban:

268

Jawaban lain hanya berfungsi untuk urutan.

Untuk setiap iterable, untuk melewati item pertama:

itercars = iter(cars)
next(itercars)
for car in itercars:
    # do work

Jika Anda ingin melewati yang terakhir, Anda dapat melakukan:

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'
agf
sumber
1
Juga melihat Sven Marnach 's jawaban
AGF
2
Saya menemukan bahwa melakukan cars.pop (0) dan cars.pop () berfungsi dengan baik.
dreamwork801
@ dreamwork801 Jawaban saya dan Sven, yang saya tautkan di komentar pertama, berfungsi untuk semua iterable, bahkan yang tak terbatas, karena mereka tidak memerlukan operasi O (n) pada data sebelum iterasi dimulai. Saran Anda, dan Abhjit, keduanya hanya bekerja untuk urutan, bukan yang bisa diubah.
agf
356

Untuk melewati elemen pertama dengan Python, Anda cukup menulis

for car in cars[1:]:
    # Do What Ever you want

atau untuk melewatkan elem terakhir

for car in cars[:-1]:
    # Do What Ever you want

Anda dapat menggunakan konsep ini untuk urutan apa pun.

Abhijit
sumber
52
Bukan untuk semua iterables , tetapi untuk semua urutan .
Sven Marnach
2
Bagaimana dengan penggunaan memori? Apakah slice membuat salinan baru dari sub-urutan?
Voyager
@ Pembawa Ya, Itu memang membuat salinan baru.
Srinivas Reddy Thatiparthy
27

Cara terbaik untuk melewatkan item pertama adalah:

from itertools import islice
for car in islice(cars, 1, None):
    # do something

islice dalam hal ini dipanggil dengan titik awal 1, dan titik akhir Tidak ada, menandakan akhir dari iterator.

Untuk dapat melewati item dari akhir iterable, Anda harus mengetahui panjangnya (selalu mungkin untuk daftar, tetapi tidak harus untuk semua yang Anda bisa ulangi). misalnya, islice (mobil, 1, len (mobil) -1) akan melewati item pertama dan terakhir dalam daftar mobil.

Roee Shenberg
sumber
Lihatlah jawaban Sven (kurang dihargai). Dia mencakup melewatkan sejumlah item yang sewenang-wenang di awal dan / atau akhir setiap iterable menggunakan islicecukup baik, tanpa mengetahui panjangnya atau menyimpan lebih banyak item dalam memori sekaligus daripada benar-benar diperlukan.
agf
Jawaban Sven sebenarnya akan menyimpan seluruh iterator dalam memori - collections.deque akan dijalankan melalui iterator. Coba lakukan sesuatu seperti collections.deque (xrange (10000000)). Tidak perlu menyimpan semua ints di memori jika Anda ingin melewatkan item pertama ...
Roee Shenberg
2
An isliceadalah apa yang diteruskan ke deque, bukan seluruh iterator, dan hanya panjang dari jumlah item yang dilewati di akhir. Itu tidak menyimpan seluruh iterator dalam memori.
agf
26

Berikut adalah fungsi generator yang lebih umum yang melewatkan sejumlah item dari awal dan akhir iterable:

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

Contoh penggunaan:

>>> list(skip(range(10), at_start=2, at_end=2))
[2, 3, 4, 5, 6, 7]
Sven Marnach
sumber
Mungkin ingin menambahkan jalur cepat untuk at_end == 0.
agf
collections.deque (...) akan segera melewati iterator. Ini berarti melewatkan (xrange (10000000), 1) akan memakan banyak memori meskipun sebenarnya tidak seharusnya.
Roee Shenberg
4
@RoeeShenberg: skip(xrange(10000000), 1)akan digunakan at_end=0, jadi parameternya deque()adalah islice(it, 0), yang hanya akan mengkonsumsi nol elemen it. Ini tidak akan menghabiskan banyak memori.
Sven Marnach
8
for item in do_not_use_list_as_a_name[1:-1]:
    #...do whatever
Logam Kurzed
sumber
3
Jangan gunakan listsebagai nama variabel
Abhijit
OP hanya ingin melewatkan elemen pertama. mengapa: -1?
luke14gratis
6
Ini sebenarnya tidak disediakan ; nama listdapat diikat kembali. Itu sebabnya Anda tidak boleh , daripada tidak bisa , menggunakannya.
jscs
@ luke14free, pertanyaannya mengatakan lompati elemen pertama, tetapi komentar kodenya menyiratkan bahwa ia benar-benar ingin melewati pertama dan terakhir.
JerseyMike
@ luke14gratis itulah yang dikatakan judulnya, bukan apa yang diketiknya di dalam kode: "lewati jika dulu atau terakhir"
KurzedMetal
3

Berdasarkan @SvenMarnach's Answer, tetapi sedikit lebih sederhana dan tanpa menggunakan 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]

Juga Perhatikan, berdasarkan timeithasil saya , ini sedikit lebih cepat daripada solusi 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
Abhijit
sumber
Dengan menggunakan tee(), Anda masih membuat seluruh daftar dalam memori untuk generator, bukan? (Anda it1)
Jabberwockey
3

Contoh:

mylist=['one'.'two','three'.'four'.'five']
for i in mylist[1:]:
   print(i)

Dalam indeks python mulai dari 0, Kita bisa menggunakan slicing operator untuk membuat manipulasi dalam iterasi.

for i in range(1,-1):
Tono Kuriakose
sumber
2

Yah, sintaks Anda sebenarnya bukan Python.

Iterasi dalam Python adalah lebih dari isi kontainer (well, secara teknis ini lebih iterators), dengan sintaks for item in container. Dalam hal ini, wadah adalah carsdaftar, tetapi Anda ingin melewatkan elemen pertama dan terakhir, sehingga artinya cars[1:-1](daftar python berbasis nol, angka negatif dihitung dari akhir, dan :mengiris sintaksis.

Jadi kamu mau

for c in cars[1:-1]:
    do something with c
Andrew Jaffe
sumber
4
Ini tidak akan berfungsi dengan iterable (misalnya generator), hanya dengan urutan.
Roee Shenberg
2

Metode alternatif:

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
pisang
sumber
2

Inilah pilihan yang saya sukai. Tidak perlu menambahkan banyak ke loop, dan hanya menggunakan alat bawaan.

Pergi dari:

for item in my_items:
  do_something(item)

untuk:

for i, item in enumerate(my_items):
  if i == 0:
    continue
  do_something(item)
komputer manusia
sumber
1

Jika carsurutan Anda bisa lakukan

for car in cars[1:-1]:
    pass
Praveen Gollakota
sumber
1

The more_itertoolsproyek meluas itertools.isliceuntuk menangani indeks negatif.

Contoh

import more_itertools as mit

iterable = 'ABCDEFGH'
list(mit.islice_extended(iterable, 1, -1))
# Out: ['B', 'C', 'D', 'E', 'F', 'G']

Oleh karena itu, Anda dapat menerapkan elemen irisan dengan elegan antara item pertama dan terakhir dari iterable:

for car in mit.islice_extended(cars, 1, -1):
    # do something
pylang
sumber
0

Saya melakukannya seperti ini, meskipun terlihat seperti retasan, ia berfungsi setiap saat:

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