ข้ามรายการแรกในการวนซ้ำในหลามหรือไม่


187

ในงูหลามฉันจะทำสิ่งที่ชอบ:

for car in cars:
   # Skip first and last, do work for rest

4
ฉันเป็นมือใหม่ แต่ฉันใช้for n, i in enumerate(cars): if n!= 0: do something to iไปแล้ว ตรรกะก็คือว่ามันจะเพิ่มเคาน์เตอร์ if n == some_value'เพื่อแต่ละค่าซึ่งคุณสามารถกำหนดเป้าหมายเช่นกับ ในตัวอย่างนี้มันจะทำอะไรกับอินสแตนซ์ของฉันแต่ละตัวยกเว้นตัวแรก
user1063287

คำตอบ:


268

คำตอบอื่น ๆ ใช้สำหรับลำดับเท่านั้น

สำหรับทุก ๆ iterable ข้ามรายการแรก:

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

หากคุณต้องการข้ามสิ่งสุดท้ายคุณสามารถทำได้:

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'

1
agf

2
ฉันพบว่าการทำรถยนต์ pop (0) และ cars.pop () ทำงานได้ดี
dreamwork801

@ dreamwork801 คำตอบและของฉัน Sven ซึ่งฉันเชื่อมโยงในความคิดเห็นแรกทำงานสำหรับ iterable ใด ๆ แม้ไม่มีที่สิ้นสุดเนื่องจากพวกเขาไม่ต้องการการดำเนินการ O (n) ข้อมูลก่อนที่จะเริ่ม ข้อเสนอแนะของคุณและของอภิสิทธิ์นั้นใช้ได้กับลำดับเท่านั้นไม่สามารถทำซ้ำได้
agf

356

หากต้องการข้ามองค์ประกอบแรกใน Python คุณสามารถเขียนได้

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

หรือข้าม elem สุดท้าย

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

คุณสามารถใช้แนวคิดนี้เพื่อลำดับใดก็ได้


52
ไม่ได้สำหรับทุกiterablesแต่สำหรับทุกลำดับ
Sven Marnach

2
วิธีการเกี่ยวกับการใช้หน่วยความจำ ฝานจัดทำสำเนาชุดย่อยใหม่หรือไม่
Voyager

@Voyager ใช่มันทำสำเนาใหม่
Srinivas Reddy Thatiparthy

27

วิธีที่ดีที่สุดในการข้ามรายการแรกคือ:

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

islice ในกรณีนี้ถูกเรียกใช้โดยมีจุดเริ่มต้นที่ 1 และจุดสิ้นสุดที่ไม่มีซึ่งแสดงถึงจุดสิ้นสุดของตัววนซ้ำ

เพื่อให้สามารถข้ามรายการจากจุดสิ้นสุดของการทำซ้ำคุณต้องทราบความยาวของมัน (เป็นไปได้เสมอสำหรับรายการ แต่ไม่จำเป็นสำหรับทุกสิ่งที่คุณสามารถทำซ้ำได้) ตัวอย่างเช่น islice (รถยนต์, 1, len (รถยนต์) -1) จะข้ามรายการแรกและสุดท้ายในรายการรถยนต์


ลองดูที่คำตอบของ Sven (ที่ประเมินค่าไม่ได้) เขาครอบคลุมการข้ามจำนวนรายการโดยพลการที่จุดเริ่มต้นและ / หรือจุดสิ้นสุดของ iterable ใด ๆ ที่ใช้isliceค่อนข้างดีโดยไม่ทราบความยาวหรือเก็บรายการเพิ่มเติมในหน่วยความจำในครั้งเดียวเกินความจำเป็นอย่างแน่นอน
agf

คำตอบของ Sven จะเก็บตัววนซ้ำทั้งหมดไว้ในหน่วยความจำ - collection.deque จะเรียกใช้ตัววนซ้ำ ลองทำบางอย่างเช่น collection.deque (xrange (10,000000)) ไม่จำเป็นต้องมีการจัดเก็บ ints ทั้งหมดที่อยู่ในหน่วยความจำถ้าคุณต้องการที่จะข้ามรายการแรกคือ ...
roee Shenberg

2
An isliceคือสิ่งที่ถูกส่งผ่านไปยังdequeไม่ใช่ตัววนซ้ำทั้งหมดและเป็นเพียงความยาวของจำนวนรายการที่จะข้ามเมื่อสิ้นสุด มันไม่ได้เก็บตัววนซ้ำทั้งหมดไว้ในหน่วยความจำ
agf

26

นี่คือฟังก์ชั่นเครื่องกำเนิดทั่วไปที่ข้ามรายการจำนวนใด ๆ ตั้งแต่เริ่มต้นและสิ้นสุดการทำซ้ำ:

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(range(10), at_start=2, at_end=2))
[2, 3, 4, 5, 6, 7]

at_end == 0อาจต้องการเพิ่มเส้นทางได้อย่างรวดเร็วสำหรับ
agf

collection.deque (... ) จะผ่านตัววนซ้ำทันที ซึ่งหมายความว่าการข้าม (xrange (10,000000), 1) จะใช้หน่วยความจำจำนวนมากถึงแม้ว่ามันจะไม่ควร
Roee Shenberg

4
@ReeeeShenberg: skip(xrange(10000000), 1)จะใช้at_end=0ดังนั้นพารามิเตอร์ที่deque()จะเป็นislice(it, 0)ซึ่งจะใช้องค์ประกอบเป็นศูนย์itเท่านั้น สิ่งนี้จะไม่ใช้หน่วยความจำมาก
Sven Marnach

8
for item in do_not_use_list_as_a_name[1:-1]:
    #...do whatever

3
อย่าใช้listเป็นชื่อตัวแปร
Abhijit

OP ต้องการข้ามองค์ประกอบแรกเท่านั้น ทำไม: -1
ลุค

6
มันไม่ได้จองจริง; ชื่อlistสามารถถูกผูกใหม่ได้ นั่นเป็นเหตุผลที่คุณไม่ควรมากกว่าไม่สามารถใช้งานได้
jscs

@ luke14free คำถามที่ว่าให้ข้ามองค์ประกอบแรก แต่ความคิดเห็นเกี่ยวกับรหัสของเขาบ่งบอกว่าเขาต้องการข้ามครั้งแรกและครั้งสุดท้าย
JerseyMike

@ luke14free นั่นคือสิ่งที่ชื่อกล่าวไม่ใช่สิ่งที่เขาพิมพ์ในรหัส: "ข้ามถ้าเป็นคนแรกหรือครั้งสุดท้าย"
KurzedMetal

3

ตามคำตอบของ @SvenMarnach แต่บิตง่ายขึ้นและไม่ต้องใช้ 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]

หมายเหตุด้วยจากtimeitผลลัพธ์ของฉันนี้จะเร็วกว่าการแก้ปัญหาเล็กน้อย

>>> 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()คุณยังคงสร้างรายการทั้งหมดในหน่วยความจำสำหรับเครื่องกำเนิดไฟฟ้าใช่ไหม (ของคุณit1)
Jabberwockey

3

ตัวอย่าง:

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

ใน python index เริ่มต้นจาก 0 เราสามารถใช้โอเปอเรเตอร์ slicing เพื่อทำการเปลี่ยนแปลงในการวนซ้ำ

for i in range(1,-1):

2

ไวยากรณ์ของคุณไม่ใช่ Python ที่เริ่มต้นจริงๆ

ซ้ำในหลามมีมากกว่าเขาเนื้อหาของภาชนะบรรจุ (ดีในทางเทคนิคมันมากกว่า iterators) for item in containerกับไวยากรณ์ ในกรณีนี้คอนเทนเนอร์เป็นcarsรายการ แต่คุณต้องการข้ามองค์ประกอบแรกและครั้งสุดท้ายดังนั้นจึงหมายความว่าcars[1:-1](รายการหลามเป็นเลขศูนย์ลบจำนวนลบนับจากท้ายและ:มีการแบ่งไวยากรณ์

ดังนั้นคุณต้องการ

for c in cars[1:-1]:
    do something with c

4
สิ่งนี้จะไม่ทำงานกับ iterable (เช่นตัวสร้าง) เฉพาะกับลำดับเท่านั้น
Roee Shenberg

2

วิธีทางเลือก:

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

2

นี่คือตัวเลือกที่ฉันต้องการ มันไม่ต้องการการเพิ่มในลูปมากและไม่ใช้อะไรนอกจากเครื่องมือในตัว

ไปจาก:

for item in my_items:
  do_something(item)

ถึง:

for i, item in enumerate(my_items):
  if i == 0:
    continue
  do_something(item)


1

more_itertoolsโครงการขยายitertools.isliceที่จะจัดการกับดัชนีเชิงลบ

ตัวอย่าง

import more_itertools as mit

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

ดังนั้นคุณสามารถใช้องค์ประกอบชิ้นอย่างหรูหราระหว่างรายการแรกและชิ้นสุดท้ายของ iterable:

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

0

ฉันทำแบบนี้แม้ว่าจะดูเหมือนว่าแฮ็คมันจะทำงานทุกครั้ง:

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.