time_interval = [4, 6, 12]
আমি [4, 4+6, 4+6+12]
তালিকা পেতে মত সংখ্যার যোগ করতে চাই t = [4, 10, 22]
।
আমি নিম্নলিখিত চেষ্টা করেছিলাম:
t1 = time_interval[0]
t2 = time_interval[1] + t1
t3 = time_interval[2] + t2
print(t1, t2, t3) # -> 4 10 22
time_interval = [4, 6, 12]
আমি [4, 4+6, 4+6+12]
তালিকা পেতে মত সংখ্যার যোগ করতে চাই t = [4, 10, 22]
।
আমি নিম্নলিখিত চেষ্টা করেছিলাম:
t1 = time_interval[0]
t2 = time_interval[1] + t1
t3 = time_interval[2] + t2
print(t1, t2, t3) # -> 4 10 22
উত্তর:
আপনি যদি এই জাতীয় অ্যারেগুলির সাথে অনেকগুলি সংখ্যক কাজ করে থাকেন তবে আমি প্রস্তাব দেব numpy
, যা একটি যোগফল যোগফলের সাথে আসে cumsum
:
import numpy as np
a = [4,6,12]
np.cumsum(a)
#array([4, 10, 22])
এই জাতীয় জিনিসের জন্য নম্পি প্রায়শই খাঁটি অজগর থেকে দ্রুততর হয়, @ অশ্বিনী এরaccumu
তুলনায় দেখুন :
In [136]: timeit list(accumu(range(1000)))
10000 loops, best of 3: 161 us per loop
In [137]: timeit list(accumu(xrange(1000)))
10000 loops, best of 3: 147 us per loop
In [138]: timeit np.cumsum(np.arange(1000))
100000 loops, best of 3: 10.1 us per loop
তবে অবশ্যই যদি আপনি একমাত্র জায়গাটি ব্যবহার করেন যে আপনি নকল ব্যবহার করেন তবে এটির উপর নির্ভরতা রাখার পক্ষে এটি উপযুক্ত নয়।
np.cumsun
রূপান্তর সময়টি বিবেচনায় নেওয়ার জন্য এটির একটি তালিকা থাকা উচিত যা একটি তালিকা দিয়ে শুরু হয়।
list
আমি সুপারিশ করব না numpy
।
পাইথন 2 এ আপনি নিজের জেনারেটরের ফাংশনটি এভাবে সংজ্ঞায়িত করতে পারেন:
def accumu(lis):
total = 0
for x in lis:
total += x
yield total
In [4]: list(accumu([4,6,12]))
Out[4]: [4, 10, 22]
এবং পাইথন ৩.২++ এ আপনি ব্যবহার করতে পারেন itertools.accumulate()
:
In [1]: lis = [4,6,12]
In [2]: from itertools import accumulate
In [3]: list(accumulate(lis))
Out[3]: [4, 10, 22]
total = 0; partial_sums = [total := total + v for v in values]
। আমি এখনও accumulate
দ্রুত হতে পারে আশা করি ।
দেখুন:
a = [4, 6, 12]
reduce(lambda c, x: c + [c[-1] + x], a, [0])[1:]
আউটপুট (আশা হিসাবে):
[4, 10, 22]
c + [c[-1] + x]
বেশি ও বেশি কাজ করার মোট ব্যয় ইনপুট দৈর্ঘ্যে মোট রানটাইম চতুর্ভুজ যুক্ত করে।
আমি পাইথন ৩.৪ দিয়ে শীর্ষ দুটি জবাবের একটি বেঞ্চ-চিহ্ন দিয়েছি এবং আমি পেয়েছি itertools.accumulate
যে numpy.cumsum
অনেক পরিস্থিতিতে দ্রুততর হয়, প্রায়শই অনেক দ্রুত। যাইহোক, আপনি মন্তব্যগুলি থেকে দেখতে পাচ্ছেন, এটি সর্বদা ক্ষেত্রে নাও হতে পারে এবং সমস্ত বিকল্প অন্বেষণ করা কঠিন। (যদি আপনার আগ্রহের আরও মাপদণ্ডের ফলাফল থাকে তবে নির্দ্বিধায় কোনও মন্তব্য যুক্ত করুন বা এই পোস্টটি সম্পাদনা করুন))
কিছু সময় ...
সংক্ষিপ্ত তালিকার accumulate
জন্য প্রায় 4 গুণ দ্রুত:
from timeit import timeit
def sum1(l):
from itertools import accumulate
return list(accumulate(l))
def sum2(l):
from numpy import cumsum
return list(cumsum(l))
l = [1, 2, 3, 4, 5]
timeit(lambda: sum1(l), number=100000)
# 0.4243644131347537
timeit(lambda: sum2(l), number=100000)
# 1.7077815784141421
দীর্ঘ তালিকাগুলির accumulate
জন্য প্রায় 3 গুণ দ্রুত:
l = [1, 2, 3, 4, 5]*1000
timeit(lambda: sum1(l), number=100000)
# 19.174508565105498
timeit(lambda: sum2(l), number=100000)
# 61.871223849244416
তাহলে numpy
array
কাস্ট করা হয় না list
, accumulate
2 গুণ দ্রুত সম্পর্কে এখনও:
from timeit import timeit
def sum1(l):
from itertools import accumulate
return list(accumulate(l))
def sum2(l):
from numpy import cumsum
return cumsum(l)
l = [1, 2, 3, 4, 5]*1000
print(timeit(lambda: sum1(l), number=100000))
# 19.18597290944308
print(timeit(lambda: sum2(l), number=100000))
# 37.759664884768426
আপনি দুটি ফাংশন বাইরে আমদানির করা এবং এখনও একটি ফিরতি তাহলে numpy
array
, accumulate
প্রায় 2 গুণ দ্রুত এখনো:
from timeit import timeit
from itertools import accumulate
from numpy import cumsum
def sum1(l):
return list(accumulate(l))
def sum2(l):
return cumsum(l)
l = [1, 2, 3, 4, 5]*1000
timeit(lambda: sum1(l), number=100000)
# 19.042188624851406
timeit(lambda: sum2(l), number=100000)
# 35.17324400227517
list
পাঁচটি আইটেমের একটিতে প্রক্রিয়াজাত করতে নিম্প ব্যবহার করবেন না , বিশেষত যদি আপনি বিনিময়ে কোনও মানতে রাজি হন না array
। যদি প্রশ্নে থাকা তালিকাটি এতই সংক্ষিপ্ত হয়, তবে তাদের চলমান সময়টি অপ্রয়োজনীয় --- নির্ভরতা এবং স্বচ্ছলতা অবশ্যই প্রভাব ফেলবে। তবে list
উল্লেখযোগ্য দৈর্ঘ্যের একরকম সংখ্যাসূচক ডেটা ধরণের প্রশস্ত ব্যবহার বোকামি হবে; তার জন্য, একটি অদ্ভুত উপযুক্ত array
হবে এবং সাধারণত দ্রুত হয়।
numpy
যদি কিছু উপেক্ষা না করি তবে কী আমি দ্রুত হতে পারি?
sum2
ফাংশনের বেশিরভাগ সময় সম্ভবত l
একটি অ্যারেতে রূপান্তরিত হয়। সময় a = np.array(l)
এবং np.cumsum(a)
পৃথক পৃথক চেষ্টা করুন । তারপরে a = np.tile(np.arange(1, 6), 1000)
বনাম চেষ্টা করুন l = [1,2,3,4,5]*1000
। অন্যান্য সংখ্যাসূচক প্রক্রিয়া পরিচালিত কোনও প্রোগ্রামে (যেমন l
প্রথম স্থানে তৈরি বা লোড করা ) আপনার কার্যকরী ডেটা সম্ভবত ইতিমধ্যে একটি অ্যারেতে থাকবে এবং তৈরিটি একটি ধ্রুবক ব্যয় হবে।
এটি ব্যবহার করে দেখুন: ফাংশন জমা করুন, অপারেটর অ্যাড সহ চলমান সংযোজন সম্পাদন করে।
import itertools
import operator
result = itertools.accumulate([1,2,3,4,5], operator.add)
list(result)
operator.add
যে কোনও উপায়ে ডিফল্ট অপারেশন সংযোজন হিসাবে আপনাকে পাস করার দরকার নেই ।
আপনি সাধারণ for
লুপের সাথে রৈখিক সময়ে ক্রমসংখ্যক যোগফলের গণনা করতে পারেন :
def csum(lst):
s = lst.copy()
for i in range(1, len(s)):
s[i] += s[i-1]
return s
time_interval = [4, 6, 12]
print(csum(time_interval)) # [4, 10, 22]
স্ট্যান্ডার্ড লাইব্রেরির itertools.accumulate
দ্রুত বিকল্প হতে পারে (যেহেতু এটি সি তে প্রয়োগ করা হয়েছে):
from itertools import accumulate
time_interval = [4, 6, 12]
print(list(accumulate(time_interval))) # [4, 10, 22]
values = [4, 6, 12]
total = 0
sums = []
for v in values:
total = total + v
sums.append(total)
print 'Values: ', values
print 'Sums: ', sums
এই কোড চালনা দেয়
Values: [4, 6, 12]
Sums: [4, 10, 22]
পাইথন 3- i
তে মূল তালিকার প্রথম আই +1 উপাদানের যোগফলের তালিকার সংখ্যাসমূহের সন্ধান করতে আপনি এটি করতে পারেন:
a = [4 , 6 , 12]
b = []
for i in range(0,len(a)):
b.append(sum(a[:i+1]))
print(b)
অথবা আপনি তালিকা বোঝার ব্যবহার করতে পারেন:
b = [sum(a[:x+1]) for x in range(0,len(a))]
আউটপুট
[4,10,22]
যদি আপনি ২. in এ কাজ না করে অজগর উপায় চান তবে এটি করা আমার উপায়
l = [1,2,3,4]
_d={-1:0}
cumsum=[_d.setdefault(idx, _d[idx-1]+item) for idx,item in enumerate(l)]
এখন আসুন এটি চেষ্টা করে দেখুন এবং এটি অন্যান্য সমস্ত প্রয়োগের বিপরীতে পরীক্ষা করুন
import timeit, sys
L=list(range(10000))
if sys.version_info >= (3, 0):
reduce = functools.reduce
xrange = range
def sum1(l):
cumsum=[]
total = 0
for v in l:
total += v
cumsum.append(total)
return cumsum
def sum2(l):
import numpy as np
return list(np.cumsum(l))
def sum3(l):
return [sum(l[:i+1]) for i in xrange(len(l))]
def sum4(l):
return reduce(lambda c, x: c + [c[-1] + x], l, [0])[1:]
def this_implementation(l):
_d={-1:0}
return [_d.setdefault(idx, _d[idx-1]+item) for idx,item in enumerate(l)]
# sanity check
sum1(L)==sum2(L)==sum3(L)==sum4(L)==this_implementation(L)
>>> True
# PERFORMANCE TEST
timeit.timeit('sum1(L)','from __main__ import sum1,sum2,sum3,sum4,this_implementation,L', number=100)/100.
>>> 0.001018061637878418
timeit.timeit('sum2(L)','from __main__ import sum1,sum2,sum3,sum4,this_implementation,L', number=100)/100.
>>> 0.000829620361328125
timeit.timeit('sum3(L)','from __main__ import sum1,sum2,sum3,sum4,this_implementation,L', number=100)/100.
>>> 0.4606760001182556
timeit.timeit('sum4(L)','from __main__ import sum1,sum2,sum3,sum4,this_implementation,L', number=100)/100.
>>> 0.18932826995849608
timeit.timeit('this_implementation(L)','from __main__ import sum1,sum2,sum3,sum4,this_implementation,L', number=100)/100.
>>> 0.002348129749298096
তালিকার দৈর্ঘ্য এবং কার্য সম্পাদনের উপর নির্ভর করে এর জন্য অনেক উত্তর থাকতে পারে be একটি খুব সহজ উপায় যা আমি পারফরম্যান্সের কথা চিন্তা না করে ভাবতে পারি তা হ'ল:
a = [1, 2, 3, 4]
a = [sum(a[0:x:1]) for x in range(len(a)+1)][1:]
print(a)
[1, 3, 6, 10]
এটি তালিকা বোধগম্যতা ব্যবহার করে এবং এটি মোটামুটিভাবে ভালভাবে কাজ করতে পারে এটি কেবল এখানেই আমি সুবারির উপর বহুবার যুক্ত করছি, আপনি সম্ভবত এটির উন্নতি করতে পারেন এবং এটিকে সহজ করে তুলতে পারেন!
আপনার প্রয়াসে চিয়ার্স!
প্রথমত, আপনি অনুচ্ছেদের একটি চলমান তালিকা চান:
subseqs = (seq[:i] for i in range(1, len(seq)+1))
তারপরে আপনি কেবল sum
প্রতিটি অনুচ্ছেদে কল করবেন :
sums = [sum(subseq) for subseq in subseqs]
(এটি করার সর্বাধিক দক্ষ উপায় নয়, কারণ আপনি সমস্ত উপসর্গ বারবার যুক্ত করছেন But তবে এটি সম্ভবত বেশিরভাগ ব্যবহারের ক্ষেত্রে গুরুত্বপূর্ণ নয়, এবং আপনার যদি ভাবতে না হয় তবে এটি বোঝা সহজ চলমান মোট।)
আপনি যদি পাইথন ৩.২ বা আরও বেশি ব্যবহার করেন তবে আপনি এটি ব্যবহার করতে পারেন itertools.accumulate
:
sums = itertools.accumulate(seq)
এবং যদি আপনি 3.1 ব্যবহার করছেন বা আগে, আপনি শুধু "সমতুল্য থেকে" উৎস সোজা আউট ডক্সের (পরিবর্তন ছাড়া অনুলিপি করতে পারেন next(it)
থেকে it.next()
2.5 এবং তার আগে জন্য)।
range
এটিকে ঘিরে হ্যাক করার চেয়ে [1:]
বা এটিকে উপেক্ষা করার চেয়ে বেশি ।)
[4,6,12]
যেহেতু আংশিক পরিমাণ পাওয়ার দরকার নেই , কারণ তিনি প্রশ্নে লিখেছেন, ইতিমধ্যে তিনি জানেন যে এটি কী!
In [42]: a = [4, 6, 12]
In [43]: [sum(a[:i+1]) for i in xrange(len(a))]
Out[43]: [4, 10, 22]
এই slighlty ছোট তালিকার জন্য @Ashwini করে উপরের দ্রুত জেনারেটরের পন্থার চেয়ে
In [48]: %timeit list(accumu([4,6,12]))
100000 loops, best of 3: 2.63 us per loop
In [49]: %timeit [sum(a[:i+1]) for i in xrange(len(a))]
100000 loops, best of 3: 2.46 us per loop
বৃহত তালিকার জন্য, জেনারেটরটি নিশ্চিত হওয়ার উপায়। । ।
In [50]: a = range(1000)
In [51]: %timeit [sum(a[:i+1]) for i in xrange(len(a))]
100 loops, best of 3: 6.04 ms per loop
In [52]: %timeit list(accumu(a))
10000 loops, best of 3: 162 us per loop
কিছুটা কৃপণ, তবে মনে হয় এটি কাজ করছে:
def cumulative_sum(l):
y = [0]
def inc(n):
y[0] += n
return y[0]
return [inc(x) for x in l]
আমি ভেবেছিলাম যে অভ্যন্তরীণ ফাংশনটি y
বাইরের লেক্সিকাল স্কোপগুলিতে ঘোষিত সংশোধন করতে সক্ষম হবে , তবে এটি কার্যকর হয়নি, সুতরাং আমরা পরিবর্তে কিছু কাঠিন্যপূর্ণ হ্যাক খেলি। জেনারেটর ব্যবহার করা সম্ভবত এটি আরও মার্জিত is
নম্পিকে ব্যবহার না করেই আপনি সরাসরি অ্যারের উপরে লুপ করতে পারেন এবং রাস্তায় যোগফল সংগ্রহ করতে পারেন। উদাহরণ স্বরূপ:
a=range(10)
i=1
while((i>0) & (i<10)):
a[i]=a[i-1]+a[i]
i=i+1
print a
ফলাফল স্বরূপ:
[0, 1, 3, 6, 10, 15, 21, 28, 36, 45]
সংক্ষিপ্ত যোগফলের জন্য খাঁটি অজগর অনেলাইনার:
cumsum = lambda X: X[:1] + cumsum([X[0]+X[1]] + X[2:]) if X[1:] else X
এটি পুনরাবৃত্তিমূলক অঙ্কের দ্বারা অনুপ্রাণিত একটি পুনরাবৃত্ত সংস্করণ । কিছু ব্যাখ্যা:
X[:1]
পূর্ববর্তী উপাদানযুক্ত একটি তালিকা এবং প্রায় একই [X[0]]
(যা খালি তালিকার জন্য অভিযোগ করবে)।cumsum
দ্বিতীয় মেয়াদে পুনরাবৃত্ত কলটি বর্তমান উপাদান [1]
এবং অবশিষ্ট তালিকা প্রসেস করে যার দৈর্ঘ্য এক দ্বারা হ্রাস পাবে।if X[1:]
এর জন্য ছোট if len(X)>1
।পরীক্ষা:
cumsum([4,6,12])
#[4, 10, 22]
cumsum([])
#[]
এবং ক্রমবর্ধমান পণ্যের জন্য সিমুলার:
cumprod = lambda X: X[:1] + cumprod([X[0]*X[1]] + X[2:]) if X[1:] else X
পরীক্ষা:
cumprod([4,6,12])
#[4, 24, 288]
এখানে আরও একটি মজাদার সমাধান। এটি কোনও locals()
বোধগতির ডিকের সুবিধা গ্রহণ করে , অর্থাৎ তালিকার বোধগমের সুযোগের ভিতরে উত্পন্ন স্থানীয় পরিবর্তনগুলি:
>>> [locals().setdefault(i, (elem + locals().get(i-1, 0))) for i, elem
in enumerate(time_interval)]
[4, 10, 22]
locals()
প্রতিটি পুনরাবৃত্তির জন্য যা দেখায় তা এখানে :
>>> [[locals().setdefault(i, (elem + locals().get(i-1, 0))), locals().copy()][1]
for i, elem in enumerate(time_interval)]
[{'.0': <enumerate at 0x21f21f7fc80>, 'i': 0, 'elem': 4, 0: 4},
{'.0': <enumerate at 0x21f21f7fc80>, 'i': 1, 'elem': 6, 0: 4, 1: 10},
{'.0': <enumerate at 0x21f21f7fc80>, 'i': 2, 'elem': 12, 0: 4, 1: 10, 2: 22}]
ছোট তালিকাগুলির জন্য পারফরম্যান্স ভয়ানক নয়:
>>> %timeit list(accumulate([4, 6, 12]))
387 ns ± 7.53 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
>>> %timeit np.cumsum([4, 6, 12])
5.31 µs ± 67.8 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
>>> %timeit [locals().setdefault(i, (e + locals().get(i-1,0))) for i,e in enumerate(time_interval)]
1.57 µs ± 12 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
এবং স্পষ্টতই বৃহত্তর তালিকার জন্য সমতল।
>>> l = list(range(1_000_000))
>>> %timeit list(accumulate(l))
95.1 ms ± 5.22 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
>>> %timeit np.cumsum(l)
79.3 ms ± 1.07 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
>>> %timeit np.cumsum(l).tolist()
120 ms ± 1.23 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
>>> %timeit [locals().setdefault(i, (e + locals().get(i-1, 0))) for i, e in enumerate(l)]
660 ms ± 5.14 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
যদিও পদ্ধতিটি কুরুচিপূর্ণ এবং ব্যবহারিক নয়, এটি অবশ্যই মজাদার।
lst = [4,6,12]
[sum(lst[:i+1]) for i in xrange(len(lst))]
আপনি যদি আরও কার্যকর সমাধান (বৃহত তালিকাগুলি?) সন্ধান করছেন তবে একটি জেনারেটর একটি ভাল কল হতে পারে (বা numpy
যদি আপনি সত্যিকারের যত্ন নিতে পারেন তবে কেবল ব্যবহার করুন )।
def gen(lst):
acu = 0
for num in lst:
yield num + acu
acu += num
print list(gen([4, 6, 12]))
এটি হ্যাস্কেল-স্টাইল হবে:
def wrand(vtlg):
def helpf(lalt,lneu):
if not lalt==[]:
return helpf(lalt[1::],[lalt[0]+lneu[0]]+lneu)
else:
lneu.reverse()
return lneu[1:]
return helpf(vtlg,[0])