2010-06-07 38 views
160

thể trùng lặp:
What is the most “pythonic” way to iterate over a list in chunks?Làm cách nào để lặp qua danh sách theo cặp?

Tôi muốn lặp thông qua một danh sách Python và quá trình 2 mục danh sách ở một thời điểm. Nội dung như thế này bằng một ngôn ngữ khác:

for(int i = 0; i < list.length(); i+=2) 
{ 
    // do something with list[i] and list[i + 1] 
} 

Cách tốt nhất để thực hiện việc này là gì?

+1

Hãy xem câu trả lời cho câu hỏi này: http://stackoverflow.com/questions/434287/what-is-the-most-pythonic-way-to-iterate-over-a-list-in-chunks –

+0

Bạn đang sử dụng phiên bản Python nào? –

+0

@Mark Byers - 2.6 – froadie

Trả lời

233

Bạn có thể sử dụng cho trong phạm vi với một kích thước bước 2:

Python 2

Python 3

for i in range(0,10,2): 
    print(i) 

Lưu ý: Sử dụng xrange trong Python 2 thay vì phạm vi vì nó hiệu quả hơn vì nó xóa một đối tượng có thể lặp lại, chứ không phải toàn bộ danh sách.

+25

+1. Cần lưu ý rằng bạn đang mô tả xrange và phạm vi của Python 2. Trong Python 3, range() tạo ra một đối tượng có thể lặp lại. –

+1

trong Python 3, phạm vi() có kích thước bước tùy chọn và xrange() không còn tồn tại –

37

Nếu bạn đang sử dụng Python 2.6 hoặc mới hơn, bạn có thể sử dụng mú recipe từ itertools mô-đun:

from itertools import izip_longest 

def grouper(n, iterable, fillvalue=None): 
    "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx" 
    args = [iter(iterable)] * n 
    return izip_longest(fillvalue=fillvalue, *args) 

Gọi như thế này:

for item1, item2 in grouper(2, l): 
    # Do something with item1 and item2 

Lưu ý rằng trong Python 3.x bạn nên sử dụng zip_longest thay vì izip_longest.

+0

+1 Đây là phương pháp mà tài liệu tự đề xuất. – Brian

+0

chỉ trong trường hợp bạn đang tự hỏi làm thế nào nó hoạt động, xem xét tất cả các vòng lặp trong args trước với nhau để izip sẽ luôn luôn có yếu tố tiếp theo khi gọi next() trên các đối số của nó – user110954

0

Nếu bạn có kiểm soát cấu trúc của danh sách, điều pythonic nhất để làm điều có lẽ sẽ thay đổi nó từ:

l=[1,2,3,4] 

tới:

l=[(1,2),(3,4)] 

Sau đó, vòng lặp của bạn sẽ là:

for i,j in l: 
    print i, j 
+7

Đó là thuộc tính đang được đọc từ một tệp bên ngoài. Tôi không thể kiểm soát danh sách và tôi thực sự đang cố gắng thay đổi nó từ 'l = [1,2,3,4]' thành 'l = [(1,2), (3,4)] 'đó là lý do tại sao Tôi đang đặt câu hỏi – froadie

49

Bạn cũng có thể sử dụng cú pháp này (L[start:stop:step]):

01.235.
mylist = [1,2,3,4,5,6,7,8,9,10] 
for i in mylist[::2]: 
    print i, 
# prints 1 3 5 7 9 

for i in mylist[1::2]: 
    print i, 
# prints 2 4 6 8 10 

Trường hợp chữ số đầu tiên là chỉ mục bắt đầu (mặc định là bắt đầu danh sách hoặc 0), thứ hai là kết thúc chỉ mục lát (mặc định là kết thúc danh sách) và chữ số thứ ba là số hoặc bước.

+5

Điều này sẽ hoạt động rất tốt, miễn là danh sách 'không phải là rất lớn. Nếu 'list' _is_ rất lớn, bạn đang tạo một bản sao của nó khi bạn sử dụng cú pháp slicing ... –

+0

Đó là chính xác, thưa bạn! Cảm ơn vì đã chú ý điều đó. – jathanism

+1

Câu trả lời của bạn là tốt cho tôi khi sử dụng tham số: 'phạm vi (my_param) [:: 2]' – Eli

2
nums = range(10) 
for i in range(0, len(nums)-1, 2): 
    print nums[i] 

Kinda bẩn nhưng nó hoạt động.

+0

Xem xét 'phạm vi' /' xrange' đã được hỗ trợ để thay đổi giá trị gia tăng, giải pháp này có vẻ ngớ ngẩn. – Brian

+1

Umm, đó là thông số cuối cùng của 'dải ô' đang thực hiện ... –

+0

Giả sử rằng số là một chuỗi chúng ta không kiểm soát được. Cuộc biểu tình thực sự bắt đầu sau dòng đầu tiên mà tôi gán giá trị 'nums'. – Ishpeck

2

này có thể không nhanh như các giải pháp izip_longest (Tôi đã không thực sự kiểm tra nó), nhưng nó sẽ làm việc với python < 2,6 (izip_longest đã được bổ sung trong 2.6):

from itertools import imap 

def grouper(n, iterable): 
    "grouper(3, 'ABCDEFG') --> ('A,'B','C'), ('D','E','F'), ('G',None,None)" 
    args = [iter(iterable)] * n 

    return imap(None, *args) 

Nếu bạn cần để đi sớm hơn 2.3, bạn có thể thay thế bản đồ tích hợp cho imap. Điểm bất lợi là nó không cung cấp khả năng tùy chỉnh giá trị điền.

35

Cách đơn giản nhất trong quan điểm của tôi là chỉ này:

it = iter([1,2,3,4,5,6]) 
for x, y in zip(it, it): 
    print x, y 

Không nhập khẩu thêm hoặc bất cứ điều gì. Và rất tao nhã, theo ý kiến ​​của tôi.

+5

Điều này không hoàn toàn làm những gì câu hỏi này yêu cầu. –

+4

Chắc chắn nó không phù hợp với câu hỏi chính xác, nhưng nó làm chính xác những gì tôi đã sau. Độc đáo quá. – s29

+0

Cách thú vị để đi! – lajarre

Các vấn đề liên quan