सवाल पायथन - एक सूची के तत्वों के बीच मतभेद


संख्याओं की एक सूची को देखते हुए प्रत्येक के बीच अंतर कैसे प्राप्त करें (i) -थ और (i+1) - इसके तत्वों में से? क्या किसी को लैम्ब्डा का बेहतर इस्तेमाल करना चाहिए या शायद समझदारी की सूची होनी चाहिए?

उदाहरण: एक सूची दी गई t=[1,3,6,...] यह एक सूची खोजना है v=[2,3,...] इसलिये 3-1=2, 6-3=3, आदि।


76
2018-03-08 11:16


मूल




जवाब:


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



यदि आपको पूर्ण अंतर की आवश्यकता है, [abs(j-i) for i,j in zip(t, t[1:])] - Anil
यदि आप इसे और अधिक कुशल बनाना चाहते हैं: list(itertools.starmap(operator.sub, zip(t[1:], t))) (आयात करने के बाद itertools तथा operator)। - blhsing
वास्तव में बस list(map(operator.sub, t[1:], t[:-1])) करूँगा। - blhsing


अन्य उत्तरों सही हैं लेकिन यदि आप संख्यात्मक काम कर रहे हैं, तो आप numpy पर विचार करना चाह सकते हैं। Numpy का उपयोग, जवाब है:

v = numpy.diff(t)

72
2018-03-08 14:26





यदि आप उपयोग नहीं करना चाहते हैं numpy न zip, आप सरल (मेरी राय में सबसे सरल) समाधान का उपयोग कर सकते हैं:

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





आप उपयोग कर सकते हैं itertools.tee तथा zip परिणामस्वरूप कुशलतापूर्वक निर्माण करने के लिए:

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

या प्रयोग कर रहे हैं itertools.islice बजाय:

from itertools import islice

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

आप इसका उपयोग करने से भी बच सकते हैं itertools मॉड्यूल:

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

इन सभी समाधान निरंतर स्थान पर काम करते हैं यदि आपको सभी परिणामों को स्टोर करने और अनंत पुनरावृत्तियों का समर्थन करने की आवश्यकता नहीं है।


समाधान के कुछ माइक्रो-बेंचमार्क यहां दिए गए हैं:

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

और अन्य प्रस्तावित समाधान:

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

ध्यान दें कि:

  • zip(L[1:], L) के बराबर है zip(L[1:], L[:-1]) जबसे zip पहले से ही सबसे कम इनपुट पर समाप्त हो जाता है, हालांकि यह पूरी प्रतिलिपि से बचाता है L
  • सूचकांक द्वारा एकल तत्वों तक पहुंचना है बहुत धीमा क्योंकि हर इंडेक्स एक्सेस पायथन में एक विधि कॉल है
  • numpy.diff है धीमा क्योंकि इसे पहले कनवर्ट करना होगा list ए के लिए ndarray। जाहिर है अगर आप प्रारंभ एक साथ ndarray यह बहुत और तेज:

    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



दूसरे समाधान में, islice(seq, 1, None) के बजाय islice(seq, 1, len(seq)) यह अनंत पुनरावृत्तियों के साथ काम करता है - braham-snyder
@ ग्राहम-स्नाइडर आप सही हैं। ठीक कर दिया। धन्यवाद - Bakuriu


ठीक। मुझे लगता है कि मुझे उचित समाधान मिला है:

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

3
2018-03-08 11:25



या यह अच्छा है, लेकिन मुझे लगता है कि यह क्रमबद्ध सूची के लिए ज़िप में टी के लिए v = [x [0] -x [1] होना चाहिए (टी [1:], टी [: - 1])] - Amit Karnik


एक कार्यात्मक दृष्टिकोण:

>>> 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]

जनरेटर का उपयोग करना:

>>> 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]

सूचकांक का उपयोग करना:

>>> [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



ऑपरेटर विधि अच्छा और सुरुचिपूर्ण है - bcattle


मरे तरीके

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



का उपयोग करते हुए enumerate अपमानजनक है क्योंकि आप इसका उपयोग नहीं कर रहे हैं value। देख stackoverflow.com/a/16714453/832230 - A-B-B