2010-10-03 27 views
10
a = [5, 66, 7, 8, 9, ...] 

Có thể thực hiện lặp lại thay vì viết như thế này không?traversal theo từng cặp của một danh sách hoặc bộ phận

a[1] - a[0] 

a[2] - a[1] 

a[3] - a[2] 

a[4] - a[3] 

...

Cảm ơn bạn!

+4

tại điểm nào bạn gặp khó khăn? Mã nào bạn có cho đến nay? –

+0

có thể trùng lặp của [Python - Sự khác biệt giữa các phần tử của danh sách] (http://stackoverflow.com/questions/2400840/python-differences-between-elements-of-a-list) – SilentGhost

Trả lời

7

chắc.

for i in range(1, len(a)): 
    print a[i] - a[i-1] 

Tôi không thấy vấn đề thực sự ở đây là gì. Bạn đã đọc the python tutorial chưa?

15

cho một danh sách nhỏ trong python 2 hay bất kỳ danh sách trong python 3, bạn có thể sử dụng

[x - y for x, y in zip(a[1:], a)] 

cho một danh sách lớn hơn, bạn có thể muốn

import itertools as it 

[x - y for x, y in it.izip(a[1:], a)] 

nếu bạn đang sử dụng python 2

Và tôi sẽ xem xét viết nó như là một biểu thức máy phát điện thay vì

(x - y for x, y in it.izip(a[1:], a)) 

Điều này sẽ tránh tạo danh sách thứ hai trong bộ nhớ cùng một lúc nhưng bạn sẽ chỉ có thể lặp lại nó một lần. Nếu bạn chỉ muốn lặp lại một lần, thì điều này là lý tưởng và thật dễ dàng để thay đổi nếu bạn quyết định sau đó bạn cần truy cập ngẫu nhiên hoặc lặp lại. Đặc biệt nếu bạn định tiếp tục xử lý nó để tạo danh sách, thì tùy chọn cuối cùng này là lý tưởng.

update:

Phương pháp nhanh nhất cho đến nay là

import itertools as it 
import operator as op 

list(it.starmap(op.sub, it.izip(a[1:], a))) 

$ python -mtimeit -s's = [1, 2]*10000' '[x - y for x, y in zip(s[1:], s)]' 
100 loops, best of 3: 13.5 msec per loop 

$ python -mtimeit -s'import itertools as it; s = [1, 2]*10000' '[x - y for x, y in it.izip(s[1:], s)]' 
100 loops, best of 3: 8.4 msec per loop 

$ python -mtimeit -s'import itertools as it; import operator as op; s = [1, 2]*10000' 'list(it.starmap(op.sub, it.izip(s[1:], s)))' 
100 loops, best of 3: 6.38 msec per loop 
+8

chúng thực sự trông quá phức tạp cho một tầm thường nhiệm vụ, đặc biệt là xem xét kinh nghiệm giả định của OP. Khi nào các vòng lặp thông thường trở thành một điều xấu để sử dụng? –

+5

khi đã trở thành hai lần như chậm và cruftier để đọc hơn một hiểu. – aaronasterling

+0

Ok, tôi đã lược tả và trong trường hợp này, chúng không chậm gấp hai lần nhưng chúng vẫn chậm nhất. 16,8 msec với cùng một đầu vào như tôi hiển thị ở trên. và quan điểm của tôi về họ là tàu tuần dương để đọc vẫn còn đứng. – aaronasterling

42

Sử dụng range hoàn toàn ổn. Tuy nhiên, lập trình (như toán học) là về xây dựng trên trừu tượng. Các cặp liên tiếp [(x0, x1), (x1, x2), ..., (xn-2, xn-1)], được gọi là kết hợp theo cặp, xem ví dụ: recipe in the itertools docs. Một khi bạn có chức năng này trong bộ công cụ của bạn, bạn có thể viết:

for x, y in pairwise(xs): 
    print(y - x) 

Hoặc, như một biểu hiện phát:

consecutive_diffs = (y - x for (x, y) in pairwise(xs)) 
0

Dưới đây là ví dụ từ reciepes itertools:

from itertools import tee 

def pairwise(iterable): 
    "s -> (s0,s1), (s1,s2), (s2, s3), ..." 
    a, b = tee(iterable) 
    next(b, None) 
    return zip(a, b) 

Điều này không dễ đọc. Nếu bạn thích điều gì đó dễ hiểu hơn và hiểu cách máy phát điện hoạt động, ở đây ví dụ dài hơn một chút với cùng một kết quả:

def pairwise(it): 
    """ 
    Walk a list in overlapping pairs. 

    >>> list(pairwise([0, 1, 2, 3, 4, 5])) 
    [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)] 
    """ 
    it = iter(it) 
    start = None 
    while True: 
     if not start: 
      start = next(it) 
     end = next(it) 
     yield start, end 
     start = end 
0
def pairwise(iterable): 
    i = iter(iterable) 
    while True: 
     yield next(i), next(i, '') 
+0

Bạn nên thêm một số nhận xét vào mã. – timiTao

+0

Mặc dù mã này có thể trả lời câu hỏi, cung cấp ngữ cảnh bổ sung về lý do và/hoặc cách mã này trả lời câu hỏi cải thiện giá trị lâu dài của nó. –

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