একটি তালিকার উপাদানগুলির মধ্যে পার্থক্য সন্ধান করা


113

সংখ্যার একটি তালিকা দেওয়া, কীভাবে প্রতিটি ( i) -th উপাদান এবং এর ( i+1) -th এর মধ্যে পার্থক্য খুঁজে পাওয়া যায় ?

একটি lambdaএক্সপ্রেশন বা সম্ভবত একটি তালিকা বোঝার ব্যবহার করা ভাল ?

উদাহরণ স্বরূপ:

একটি তালিকা দেওয়া t=[1,3,6,...], লক্ষ্য একটি তালিকা খুঁজে পেতে v=[2,3,...]কারণ 3-1=2, 6-3=3ইত্যাদি

উত্তর:


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

14
আপনার যদি নিখুঁত পার্থক্যগুলির প্রয়োজন হয়, [abs(j-i) for i,j in zip(t, t[1:])]
অনিল

আপনি যদি এটিকে আরও দক্ষ করে তুলতে চান: list(itertools.starmap(operator.sub, zip(t[1:], t)))(আমদানির পরে itertoolsএবং operator)।
blhsing

3
আসলে সহজভাবে list(map(operator.sub, t[1:], t[:-1]))করবে।
15hm এ blhsing

উজ্জ্বল! আমি এই উত্তর খুব ভালবাসি!
ছাইম ফ্রিডম্যান

104

অন্যান্য উত্তরগুলি সঠিক তবে আপনি সংখ্যাসূচক কাজ করছেন, আপনি অদ্ভুত বিবেচনা করতে চাইতে পারেন। অদ্ভুত ব্যবহার করে উত্তরটি হ'ল:

v = numpy.diff(t)

খুব উপকারী! ধন্যবাদ! np.diff([2,4,9])হবে[2,5]
ট্র্যাভেলট্রেডার

এটি কি zipসংস্করণটির চেয়ে আরও দক্ষ হবে ?
ইউজার 760900

35

আপনি যদি না ব্যবহার করতে চান numpyনা zip, আপনি নিম্নলিখিত সমাধানটি ব্যবহার করতে পারেন:

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

12

আপনি ফলাফলটি দক্ষতার সাথে তৈরি করতে 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

দ্বিতীয় সমাধানে islice(seq, 1, None)পরিবর্তে islice(seq, 1, len(seq))এটি অসীম পুনরাবৃত্তকারীগুলির সাথে কাজ করে
ব্রাহাম স্নাইডার

5

:=পাইথন 3.8+ এ উপলব্ধ ওয়ালরাস অপারেটরটি ব্যবহার করে :

>>> t = [1, 3, 6]
>>> prev = t[0]; [-prev + (prev := x) for x in t[1:]]
[2, 3]

5

আমি ব্যবহার করার পরামর্শ দিতে হবে

v = np.diff(t)

এটি সহজ এবং পড়া সহজ।

কিন্তু যদি আপনি চান vমত একই দৈর্ঘ্যের আছে tতারপর

v = np.diff([t[0]] + t) # for python 3.x

অথবা

v = np.diff(t + [t[-1]])

এফওয়াইআই: এটি কেবল তালিকার জন্য কাজ করবে।

নপি অ্যারে জন্য

v = np.diff(np.append(t[0], t))

সুন্দর উত্তর, আপনি একই দৈর্ঘ্য নিশ্চিত করতে প্রিপেন্ড কীওয়ার্ডটিও ব্যবহার করতে পারেন, নীচের উত্তরটি দেখুন, যা আমার মনে হয় এটি আরও সুন্দর
অ্যাড্রিয়ান টম্পকিন্স

4

একটি কার্যকরী পদ্ধতির:

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

ঠিক আছে. আমি মনে করি আমি সঠিক সমাধানটি পেয়েছি:

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

2
হ্যাঁ এটি ভাল, তবে আমি মনে করি এটি বাছাই করা তালিকার জন্য জিপ (টি [1:], টি [: - 1])] এর জন্য ভি = [x [0] -x [1] হওয়া উচিত ছিল!
অমিত করণিক

0

পর্যায়ক্রমিক সীমানা সহ সমাধান

কখনও কখনও সংখ্যার একীকরণের সাথে আপনি পর্যায়ক্রমের সীমানা শর্তগুলির সাথে একটি তালিকার মধ্যে পার্থক্য করতে চাইবেন (সুতরাং প্রথম উপাদানটি শেষের থেকে পার্থক্য গণনা করে this এক্ষেত্রে numpy.rol ফাংশন সহায়ক:

v-np.roll(v,1)

শূন্য চাপ দেওয়া সমাধান

আরেকটি নিম্পী সমাধান (কেবলমাত্র সম্পূর্ণতার জন্য) ব্যবহার করা

numpy.ediff1d(v)

এটি numpy.diff হিসাবে কাজ করে তবে কেবল একটি ভেক্টর (এটি ইনপুট অ্যারে সমতল করে)। এটি ফলাফল ভেক্টরগুলিতে সংখ্যাগুলি সংযোজন বা সংযোজন করার ক্ষমতা সরবরাহ করে। আবহাওয়া পরিবর্তনশীল (যেমন বৃষ্টি, প্রচ্ছন্ন তাপ ইত্যাদি) ক্ষেত্রে প্রায়শই প্রবাহিত জমে থাকা ক্ষেত্রগুলি পরিচালনা করার ক্ষেত্রে এটি কার্যকর হয়, কারণ আপনি প্রথম প্রবেশপথটি আটকানো না রেখে ইনপুট ভেরিয়েবলের সমান দৈর্ঘ্যের ফলস্বরূপ তালিকা চান want

তাহলে আপনি লিখতেন

np.ediff1d(v,to_begin=v[0])

অবশ্যই, আপনি এনপি.ডিফ কমান্ডের সাহায্যে এটিও করতে পারেন, এই ক্ষেত্রে আপনাকে প্রিপেন্ড কীওয়ার্ডের সাহায্যে সিরিজে শূন্য শোধ করতে হবে:

np.diff(v,prepend=0.0) 

উপরের সমস্ত সমাধানগুলি কোনও ভেক্টরকে ফেরত দেয় যা ইনপুটটির সমান দৈর্ঘ্য।


আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.