Câu hỏi Python - Sự khác nhau giữa các phần tử của một danh sách


Đưa ra một danh sách các con số làm thế nào để tìm sự khác biệt giữa mỗi (i) -th và (i+1) -th yếu tố của nó? Nên một tốt hơn sử dụng lambda hoặc có thể danh sách hiểu?

Thí dụ: Đưa ra một danh sách t=[1,3,6,...] nó là để tìm một danh sách v=[2,3,...] bởi vì 3-1=2, 6-3=3, v.v.


76
2018-03-08 11:16


gốc




Các câu trả lời:


>>> t
[1, 3, 6]
>>> [j-i for i, j in zip(t[:-1], t[1:])]  # or use itertools.izip in py2k
[2, 3]

107
2018-03-08 11:23



Trong trường hợp bạn cần sự khác biệt tuyệt đối, [abs(j-i) for i,j in zip(t, t[1:])] - Anil
Trong trường hợp bạn muốn làm cho nó hiệu quả hơn: list(itertools.starmap(operator.sub, zip(t[1:], t))) (sau khi nhập itertools và operator). - blhsing
Thực sự đơn giản list(map(operator.sub, t[1:], t[:-1])) sẽ làm. - blhsing


Các câu trả lời khác là chính xác nhưng nếu bạn đang làm công việc số, bạn có thể muốn xem xét gumpy. Sử dụng numpy, câu trả lời là:

v = numpy.diff(t)

72
2018-03-08 14:26





Nếu bạn không muốn sử dụng numpy cũng không zip, bạn có thể sử dụng giải pháp đơn giản (theo ý kiến ​​của tôi):

>>> t = [1, 3, 6]
>>> v = [t[i+1]-t[i] for i in range(len(t)-1)]
>>> v
[2, 3]

25
2018-05-23 12:51





Bạn có thể dùng itertools.tee và zip để xây dựng hiệu quả kết quả:

from itertools import tee
# python2 only:
#from itertools import izip as zip

def differences(seq):
    iterable, copied = tee(seq)
    next(copied)
    for x, y in zip(iterable, copied):
        yield y - x

Hoặc sử dụng itertools.islice thay thế:

from itertools import islice

def differences(seq):
    nexts = islice(seq, 1, None)
    for x, y in zip(seq, nexts):
        yield y - x

Bạn cũng có thể tránh sử dụng itertools module:

def differences(seq):
    iterable = iter(seq)
    prev = next(iterable)
    for element in iterable:
        yield element - prev
        prev = element

Tất cả các giải pháp làm việc trong không gian liên tục nếu bạn không cần phải lưu trữ tất cả các kết quả và hỗ trợ lặp vô hạn.


Dưới đây là một số tiêu chuẩn vi mô của các giải pháp:

In [12]: L = range(10**6)

In [13]: from collections import deque
In [15]: %timeit deque(differences_tee(L), maxlen=0)
10 loops, best of 3: 122 ms per loop

In [16]: %timeit deque(differences_islice(L), maxlen=0)
10 loops, best of 3: 127 ms per loop

In [17]: %timeit deque(differences_no_it(L), maxlen=0)
10 loops, best of 3: 89.9 ms per loop

Và các giải pháp được đề xuất khác:

In [18]: %timeit [x[1] - x[0] for x in zip(L[1:], L)]
10 loops, best of 3: 163 ms per loop

In [19]: %timeit [L[i+1]-L[i] for i in range(len(L)-1)]
1 loops, best of 3: 395 ms per loop

In [20]: import numpy as np

In [21]: %timeit np.diff(L)
1 loops, best of 3: 479 ms per loop

In [35]: %%timeit
    ...: res = []
    ...: for i in range(len(L) - 1):
    ...:     res.append(L[i+1] - L[i])
    ...: 
1 loops, best of 3: 234 ms per loop

Lưu ý rằng:

  • zip(L[1:], L) tương đương với zip(L[1:], L[:-1]) kể từ đó zip đã chấm dứt trên đầu vào ngắn nhất, tuy nhiên nó tránh được toàn bộ bản sao của L.
  • Truy cập các phần tử đơn theo chỉ số là rất chậm vì mọi truy cập chỉ mục là một cuộc gọi phương thức trong python
  • numpy.diff Là chậm chạp bởi vì trước tiên nó phải chuyển đổi list đến một ndarray. Rõ ràng nếu bạn khởi đầu với một ndarray nó sẽ là nhiều nhanh hơn:

    In [22]: arr = np.array(L)
    
    In [23]: %timeit np.diff(arr)
    100 loops, best of 3: 3.02 ms per loop
    

8
2017-07-22 17:34



trong giải pháp thứ hai, islice(seq, 1, None) thay vì islice(seq, 1, len(seq)) làm cho nó hoạt động với các vòng lặp vô hạn - braham-snyder
@ braham-snyder Bạn nói đúng. Sửa lỗi. Cảm ơn - Bakuriu


Được. Tôi nghĩ rằng tôi đã tìm ra giải pháp thích hợp:

v = [x[1]-x[0] for x in zip(t[1:],t[:-1])]

3
2018-03-08 11:25



ya của nó tốt, nhưng tôi nghĩ rằng nó nên có được v = [x [0] -x [1] cho x trong zip (t [1:], t [: - 1])] cho danh sách được sắp xếp! - Amit Karnik


Một cách tiếp cận chức năng:

>>> import operator
>>> a = [1,3,5,7,11,13,17,21]
>>> map(operator.sub, a[1:], a[:-1])
[2, 2, 2, 4, 2, 4, 4]

Sử dụng máy phát điện:

>>> import operator, itertools
>>> g1,g2 = itertools.tee((x*x for x in xrange(5)),2)
>>> list(itertools.imap(operator.sub, itertools.islice(g1,1,None), g2))
[1, 3, 5, 7]

Sử dụng chỉ mục:

>>> [a[i+1]-a[i] for i in xrange(len(a)-1)]
[2, 2, 2, 4, 2, 4, 4]

3
2017-10-23 12:36



Phương thức toán tử đẹp và thanh lịch - bcattle


Con đường của tôi

>>>v = [1,2,3,4,5]
>>>[v[i] - v[i-1] for i, value in enumerate(v[1:], 1)]
[1, 1, 1, 1]

-1
2018-04-15 07:09



Sử dụng enumerate là lãng phí vì bạn không sử dụng value. Xem stackoverflow.com/a/16714453/832230 - A-B-B