Bỏ qua mục đầu tiên trong vòng lặp cho python?


187

Trong python, Làm thế nào để tôi làm một cái gì đó như:

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

4
Tôi là người mới, nhưng tôi đã sử dụng for n, i in enumerate(cars): if n!= 0: do something to i. logic là nó thêm một 'bộ đếm' cho mỗi giá trị mà sau đó bạn có thể nhắm mục tiêu, ví dụ như với if n == some_value. trong ví dụ này, nó sẽ làm một cái gì đó cho từng phiên bản của i, ngoại trừ trường hợp đầu tiên.
dùng1063287

Câu trả lời:


268

Các câu trả lời khác chỉ hoạt động cho một chuỗi.

Đối với bất kỳ lần lặp nào, bỏ qua mục đầu tiên:

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

Nếu bạn muốn bỏ qua lần cuối, bạn có thể làm:

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
Đồng thời xem câu trả lời của Sven Marnach
agf

2
Tôi thấy rằng làm ô tô.pop (0) và ô tô.pop () hoạt động tốt.
dreamwork801

@ dreamwork801 Câu trả lời của tôi và Sven, mà tôi liên kết trong bình luận đầu tiên, hoạt động cho bất kỳ câu hỏi lặp lại, thậm chí vô hạn nào, vì chúng không yêu cầu thao tác O (n) trên dữ liệu trước khi bắt đầu lặp. Đề xuất của bạn và Abhjit, cả hai chỉ hoạt động cho các chuỗi, không phải bất kỳ lần lặp nào.
agf

356

Để bỏ qua phần tử đầu tiên trong Python, bạn chỉ cần viết

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

hoặc bỏ qua elem cuối cùng

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

Bạn có thể sử dụng khái niệm này cho bất kỳ trình tự.


52
Không phải cho tất cả các lần lặp , nhưng cho tất cả các trình tự .
Sven Marnach

2
Làm thế nào về việc sử dụng bộ nhớ? Liệu lát cắt tạo ra một bản sao mới của chuỗi con?
Voyager

@Voyager Có, nó tạo bản sao mới.
Srinivas Reddy Thatiparthy

27

Cách tốt nhất để bỏ qua (các) mục đầu tiên là:

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

islice trong trường hợp này được gọi với điểm bắt đầu là 1 và điểm kết thúc là Không, biểu thị sự kết thúc của trình vòng lặp.

Để có thể bỏ qua các mục từ cuối của một lần lặp, bạn cần biết độ dài của nó (luôn luôn có thể cho một danh sách, nhưng không nhất thiết cho tất cả mọi thứ bạn có thể lặp lại). ví dụ, islice (ô tô, 1, len (ô tô) -1) sẽ bỏ qua các mục đầu tiên và cuối cùng trong danh sách ô tô.


Hãy xem câu trả lời của Sven (đánh giá thấp). Anh ta bỏ qua một số lượng vật phẩm tùy ý ở đầu và / hoặc cuối của bất kỳ lần lặp nào sử dụng islicekhá tốt, mà không biết độ dài hoặc lưu trữ nhiều vật phẩm trong bộ nhớ cùng một lúc là hoàn toàn cần thiết.
agf

Câu trả lời của Sven thực sự sẽ lưu trữ toàn bộ iterator trong bộ nhớ - Collection.deque sẽ chạy qua iterator. Hãy thử làm một cái gì đó như bộ sưu tập.deque (xrange (10000000)). Không cần lưu trữ tất cả các thông số trong bộ nhớ nếu bạn muốn bỏ qua mục đầu tiên ...
Roee Shenberg

2
An islicelà những gì được truyền cho deque, không phải toàn bộ vòng lặp và nó chỉ là độ dài của số lượng vật phẩm cần bỏ qua ở cuối. Nó không lưu trữ toàn bộ iterator trong bộ nhớ.
agf

26

Đây là một hàm tạo tổng quát hơn bỏ qua bất kỳ số lượng mục nào từ đầu và cuối của một lần lặp:

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

Ví dụ sử dụng:

>>> list(skip(range(10), at_start=2, at_end=2))
[2, 3, 4, 5, 6, 7]

Có thể muốn thêm một con đường nhanh cho at_end == 0.
agf

bộ sưu tập.deque (...) sẽ ngay lập tức đi qua trình vòng lặp. Điều này có nghĩa là bỏ qua (xrange (10000000), 1) sẽ chiếm rất nhiều bộ nhớ mặc dù thực sự không nên.
Roee Shenberg

4
@RoeeShenberg: skip(xrange(10000000), 1)sẽ sử dụng at_end=0, vì vậy tham số deque()sẽ là islice(it, 0), sẽ chỉ tiêu thụ các phần tử bằng không it. Điều này sẽ không chiếm nhiều bộ nhớ.
Sven Marnach

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

3
Đừng sử dụng listlàm tên biến
Abhijit

OP chỉ muốn bỏ qua yếu tố đầu tiên. tại sao: -1?
luke14free

6
Nó không thực sự được bảo lưu ; tên listcó thể được ràng buộc lại. Đó là lý do tại sao bạn không nên , thay vì không thể , sử dụng nó.
jscs

@ luke14free, câu hỏi nói bỏ qua yếu tố đầu tiên, nhưng nhận xét mã của anh ta ngụ ý rằng anh ta thực sự muốn bỏ qua đầu tiên và cuối cùng.
JerseyMike

@ luke14free đó là những gì tiêu đề nói, không phải những gì anh ấy đã nhập bên trong mã: "bỏ qua nếu đầu tiên hoặc cuối cùng"
KurzingMetal

3

Dựa trên Câu trả lời của @SvenMarnach, nhưng đơn giản hơn một chút và không sử dụng 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]

Cũng lưu ý, dựa trên timeitkết quả của tôi , điều này nhanh hơn một chút so với giải pháp 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

Bằng cách sử dụng tee(), bạn vẫn đang tạo toàn bộ danh sách trong bộ nhớ cho trình tạo, phải không? (của bạn it1)
Jabberw

3

Thí dụ:

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

Trong chỉ mục python bắt đầu từ 0, Chúng ta có thể sử dụng toán tử cắt để thực hiện các thao tác lặp.

for i in range(1,-1):

2

Chà, cú pháp của bạn không thực sự là Python để bắt đầu.

Lặp đi lặp lại trong Python là nội dung của các container (tốt, về mặt kỹ thuật, nó là trên các trình vòng lặp), với một cú pháp for item in container. Trong trường hợp này, container là carsdanh sách, nhưng bạn muốn bỏ qua các phần tử đầu tiên và cuối cùng, vì vậy điều đó có nghĩa là cars[1:-1](danh sách python là dựa trên số không, số âm được tính từ cuối và :đang cắt cú pháp.

Vậy bạn muốn

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

4
Điều này sẽ không hoạt động với một trình lặp (ví dụ: trình tạo), chỉ với một chuỗi.
Roee Shenberg

2

Một phương pháp khác:

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

Đây là lựa chọn ưa thích của tôi. Nó không yêu cầu thêm nhiều vào vòng lặp và không sử dụng gì ngoài các công cụ tích hợp.

Đi từ:

for item in my_items:
  do_something(item)

đến:

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


1

Các more_itertoolsdự án mở rộng itertools.isliceđể xử lý các chỉ số tiêu cực.

Thí dụ

import more_itertools as mit

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

Do đó, bạn có thể áp dụng nó một cách tao nhã các phần tử giữa các mục đầu tiên và cuối cùng của một lần lặp:

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

0

Tôi làm như thế này, mặc dù nó trông giống như một bản hack nhưng nó hoạt động mọi lúc:

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.