একটি তালিকার পণ্য ফিরে


157

নিম্নলিখিতগুলি করার জন্য আরও সংক্ষিপ্ত, দক্ষ বা কেবল অজগর উপায় আছে কি?

def product(list):
    p = 1
    for i in list:
        p *= i
    return p

সম্পাদনা করুন:

আমি আসলে দেখতে পেলাম যে এটি অপারেটর.মুল ব্যবহারের চেয়ে সামান্য দ্রুত:

from operator import mul
# from functools import reduce # python3 compatibility

def with_lambda(list):
    reduce(lambda x, y: x * y, list)

def without_lambda(list):
    reduce(mul, list)

def forloop(list):
    r = 1
    for x in list:
        r *= x
    return r

import timeit

a = range(50)
b = range(1,50)#no zero
t = timeit.Timer("with_lambda(a)", "from __main__ import with_lambda,a")
print("with lambda:", t.timeit())
t = timeit.Timer("without_lambda(a)", "from __main__ import without_lambda,a")
print("without lambda:", t.timeit())
t = timeit.Timer("forloop(a)", "from __main__ import forloop,a")
print("for loop:", t.timeit())

t = timeit.Timer("with_lambda(b)", "from __main__ import with_lambda,b")
print("with lambda (no 0):", t.timeit())
t = timeit.Timer("without_lambda(b)", "from __main__ import without_lambda,b")
print("without lambda (no 0):", t.timeit())
t = timeit.Timer("forloop(b)", "from __main__ import forloop,b")
print("for loop (no 0):", t.timeit())

আমাকে দেয়

('with lambda:', 17.755449056625366)
('without lambda:', 8.2084708213806152)
('for loop:', 7.4836349487304688)
('with lambda (no 0):', 22.570688009262085)
('without lambda (no 0):', 12.472226858139038)
('for loop (no 0):', 11.04065990447998)

3
সেখানে অপশন একটি খালি তালিকার জন্য যে এখানে দেওয়া মধ্যে একটি কার্মিক পার্থক্য reduceউত্তর একটি বাড়াতে TypeErrorযেহেতু, forলুপ উত্তর ফেরৎ 1. এই একটি বাগ সংশোধন করা হয় forলুপ উত্তর (একটি খালি তালিকা গুণফল আর 1 তুলনায় এটি 17 বা 'আর্মাদিলো')।
স্কট গ্রিফিথস

5
দয়া করে আপনার ভেরিয়েবলের নামের জন্য বিল্ট-ইনগুলির নাম (যেমন তালিকা) ব্যবহার এড়াতে চেষ্টা করুন।
মার্ক বাইয়ার্স

2
পুরানো উত্তর, তবে আমি সম্পাদনা করতে প্রলুব্ধ হলাম এটি listভেরিয়েবল নাম হিসাবে ব্যবহার না করে ...
beroe

13
খালি তালিকার পণ্যটি হ'ল 1. en.wikiki.org/wiki/Empty_product
পল

1
@ স্কটগ্রিফিটসগুলিকে আমার উল্লেখ করা উচিত ছিল যে আমি সংখ্যার একটি তালিকা বুঝি। এবং আমি বলব যে খালি তালিকার যোগফলটি +সেই ধরণের তালিকার (একইভাবে পণ্য / পণ্যের জন্য *) পরিচয় উপাদান । এখন আমি বুঝতে পারি যে পাইথনটি গতিশীলভাবে টাইপ করা হয়েছে যা জিনিসগুলিকে আরও শক্ত করে তোলে, তবে হাস্কেলের মতো স্ট্যাটিক টাইপ সিস্টেমের সাথে বুদ্ধিমান ভাষায় এটি একটি সমাধান সমস্যা। তবে Pythonকেবল sumকোনও সংখ্যাতে কাজ করার অনুমতি দেয় , যেহেতু sum(['a', 'b'])এমনকি কাজ করে না, তাই আমি আবার বলি যে এটি পণ্যের 0জন্য sumএবং তার 1জন্য অর্থবোধ করে।
সেমিকোলন

উত্তর:


169

ল্যাম্বদা ব্যবহার না করে:

from operator import mul
reduce(mul, list, 1)

এটা আরও ভাল এবং দ্রুত। পাইথন সহ 2.7.5

from operator import mul
import numpy as np
import numexpr as ne
# from functools import reduce # python3 compatibility

a = range(1, 101)
%timeit reduce(lambda x, y: x * y, a)   # (1)
%timeit reduce(mul, a)                  # (2)
%timeit np.prod(a)                      # (3)
%timeit ne.evaluate("prod(a)")          # (4)

নিম্নলিখিত কনফিগারেশন:

a = range(1, 101)  # A
a = np.array(a)    # B
a = np.arange(1, 1e4, dtype=int) #C
a = np.arange(1, 1e5, dtype=float) #D

অজগর ২.7.৫ সহ ফলাফল

       | 1 | 2 | 3 | 4 |
------- + + ----------- + + ----------- + + ----------- + + ------ ----- + +
 একটি 20.8 µs 13.3 22s 22.6 39s 39.6 µ এস     
 বি 106 95s 95.3 µs 5.92 26s 26.1। এস
 সি 4.34 এমএস 3.51 এমএস 16.7 38s 38.9 µ এস
 ডি 46.6 এমএস 38.5 এমএস 180 µ এস 216 µ এস

ফলাফল: np.prodআপনি যদি np.arrayডেটা স্ট্রাকচার হিসাবে ব্যবহার করেন তবে দ্রুততম এটি (ছোট অ্যারের জন্য 18x, বড় অ্যারের জন্য 250x)

অজগর সহ 3.3.2:

       | 1 | 2 | 3 | 4 |
------- + + ----------- + + ----------- + + ----------- + + ------ ----- + +
 একটি 23.6 12s 12.3 68s 68.6 84s 84.9 µs     
 বি 133 10s 107 7s 7.42 27s 27.5 µs
 সি 4.79 এমএস 3.74 এমএস 18.6 ডিগ্রি 40.9 µ এস
 ডি 48.4 এমএস 36.8 এমএস 187 21 এস 214 µ এস

অজগর 3 ধীর?


1
খুব আকর্ষণীয়, ধন্যবাদ। পাইথন 3 ধীর হতে পারে এমন কোনও ধারণা?
সাইমন ওয়াটকিন্স

3
সম্ভাব্য কারণগুলি: (1) পাইথন 3 intহল পাইথন 2 long। পাইথন 2 "বিট" ব্যবহার করবে যতক্ষণ না এটি 32 টি বিট উপচে পড়ে; পাইথন 3 শুরু থেকেই "দীর্ঘ" ব্যবহার করবে। (২) পাইথন 3.0 ছিল একটি "ধারণার প্রমাণ"। এএসএপ 3.1 এ আপগ্রেড করুন!
জন মাচিন

1
পাইথন 2.6: আমি একটি অন্য মেশিনে একই পরীক্ষা redone করেছি ( 'ল্যামডা সঙ্গে', 21.843887090682983) ( 'ল্যামডা ছাড়া:', 9.7096879482269287) পাইথন 3.1: ল্যামডা সঙ্গে 24,7712180614 ল্যামডা ছাড়া: 10,7758350372
Ruggero Turra

1
দু'জনেই খালি তালিকা দিয়ে ব্যর্থ হয়।
বাগ

9
নোট করুন যে আপনাকে পাইথন ৩. আইইউর মধ্যে মডিউলটি reduceথেকে অপারেটরটি আমদানি করতে হবে । functoolsfrom functools import reduce
ক্রিস

50
reduce(lambda x, y: x * y, list, 1)

3
+1 তবে এটি করার আরও operator.mulভাল উপায়ের জন্য @ উইশোর উত্তর দেখুন ।
ক্রিস লুটজ

অপারেটর.মুল x * y এর চেয়ে কেন পছন্দনীয়?
অ্যাডাম হিউজ

2
অপারেটর.মুল একটি ফাংশন এবং সুতরাং এটি কেবল এক্স * ওয়াইয়ের জন্য নয় পুরো ল্যাম্বডা এক্সপ্রেশনটির (যেমন প্রথম যুক্তি reduce) জন্য প্রতিস্থাপন হবে
জোহানেস চরারা

6
from functools import reduceপাইথন 3 এ এটির কাজ করতে আপনাকে একটি আমদানি করতে হবে
লাইফব্লেন্স

45

আপনার তালিকায় যদি কেবলমাত্র নম্বর থাকে:

from numpy import prod
prod(list)

সম্পাদনা : @ অফ99555 দ্বারা নির্দেশিত হিসাবে এটি বৃহত্তর পূর্ণসংখ্যার ফলাফলের জন্য কাজ করে না যেখানে এটি টাইপের ফলাফল দেয় numpy.int64যখন ইয়ান ক্লেল্যান্ডের সমাধান ভিত্তিক operator.mulএবং reduceবড় সংখ্যার ফলাফলের জন্য কাজ করে কারণ এটি ফিরে আসে long


তালিকাটি সংক্ষিপ্ত হলে এটি ধীর
এন্ডোলিথ

1
আমি মূল্যায়নের চেষ্টা করেছি from numpy import prod; prod(list(range(5,101)))এবং এটি আউটপুট হয়েছে 0, আপনি কি পাইথন 3 এ এই ফলাফলটি পুনরুত্পাদন করতে পারেন?
অফ 99555

1
কারণ এই ক্ষেত্রে prodটাইপের ফল দেয় numpy.int64এবং আপনি ইতিমধ্যে এর জন্য একটি ওভারফ্লো (একটি নেতিবাচক মান) পান range(5,23)। বৃহত্তর পূর্ণসংখ্যার ভিত্তিতে operator.mulএবং এর reduceজন্য @ ইয়ান ক্লেল্যান্ডের দ্রবণটি ব্যবহার করুন (এটি সেক্ষেত্রে longস্বেচ্ছাচারিত নির্ভুলতা বলে মনে হয়) a
আন্দ্রে হল্জনার

@ অফ99555 দুটি সমাধান: হয় ফ্লোট টাইপের তালিকা দিয়ে শুরু করুন np.prod(np.arange(5.0,101.0))বা এটি করে ফ্লোটে রূপান্তর করুন np.prod(np.array(range(5,101)).astype(np.float64))। মনে রাখবেন যে NumPy এর np.float64পরিবর্তে ব্যবহার করে float। আমি পার্থক্য জানি না।
কাঠ

22

আপনি যদি কিছু করতে পারেন তবে আমদানি না করে যদি আপনি সত্যিই এটির একটি লাইন তৈরি করতে চান:

eval('*'.join(str(item) for item in list))

কিন্তু না।


মোটামুটি পাইথোনিক সংক্ষেপে
জিতিন

18
import operator
reduce(operator.mul, list, 1)

1
শেষ যুক্তি (1) সত্যিই প্রয়োজনীয়?
রাগেরো তুররা

10
তালিকাটি খালি থাকতে পারলে শেষ যুক্তিটি প্রয়োজনীয়, অন্যথায় এটি টাইপআরর ব্যতিক্রম ছুঁড়ে দেবে। অবশ্যই, কখনও কখনও একটি ব্যতিক্রম আপনি যা চান তা হতে পারে।
ডেভ কার্বি

2
আমার জন্য এটি তর্ক ছাড়াই 0 ফেরত দেয়, তাই আপনি খালি পণ্য কনভেনশনটি প্রয়োগ করাও এটি বিবেচনা করতে পারেন।
বাগ

বা functools.reduce(..)python3
আন্দ্রে Holzner

18

শুরু করে Python 3.8, একটি prodফাংশনটি mathস্ট্যান্ডার্ড লাইব্রেরিতে মডিউলটিতে অন্তর্ভুক্ত করা হয়েছে :

গণিত.প্রড (পুনরাবৃত্ত, *, শুরু = 1)

যা কোনও startমানের পুনরাবৃত্ত হয় (ডিফল্ট: 1) সংখ্যার পুনরাবৃত্তিযোগ্য:

import math

math.prod([2, 3, 4]) # 24

দ্রষ্টব্য যে যদি পুনরাবৃত্তিযোগ্য খালি হয় তবে 1এটি উত্পাদন করবে (বা startযদি সরবরাহ করা হয় তবে মান)।


15

আমি কম.এল.পিথনে কিছু দীর্ঘ আলোচনা মনে করি (দুঃখিত, এখন পয়েন্টার উত্পাদন করতে খুব অলস) যা এই সিদ্ধান্তে পৌঁছেছে যে আপনার মূল product()সংজ্ঞাটি সর্বাধিক পাইথোনিক

নোট করুন যে প্রস্তাবটি প্রতিবার আপনি এটি করতে চাইলে লুপের জন্য নয়, একবার একবার কোনও ফাংশন লিখতে (প্রতি হ্রাসের প্রকারে) লিখে প্রয়োজন হিসাবে কল করুন! কলকরণ হ্রাস ফাংশনগুলি খুব পাইথোনিক - এটি জেনারেটর এক্সপ্রেশনগুলির সাথে মিষ্টিভাবে কাজ করে এবং যেহেতু এটির প্রচলিত সূচনা হওয়ার ফলে sum()পাইথন আরও বেশি সংখ্যক বিল্টিন হ্রাস কার্যকারিতা বৃদ্ধি করে চলেছে - any()এবংall() সর্বশেষতম সংযোজনগুলি ...

এই উপসংহারটি দয়ালু আধিকারিক - পাইথন 3.0 এর বিল্টিনগুলি থেকে সরানোreduce() হয়েছিল , এই বলে:

"আপনার functools.reduce()যদি সত্যিই এটির প্রয়োজন হয় তা ব্যবহার করুন ; তবে, লুপের জন্য একটি সুস্পষ্ট সময়ের 99 শতাংশ বেশি পাঠযোগ্য।"

গুইডোর সমর্থনমূলক উক্তির জন্য পাইথন 3000 এ () কমিয়ে আনার ভাগ্যও দেখুন (এবং সেই ব্লগটি পড়ার জন্য লিসপারদের দ্বারা কিছু কম সমর্থনকারী মন্তব্য)।

পিএস যদি চান্সক্রমে আপনার product()সংযুক্তিগুলির প্রয়োজন হয় , দেখুন math.factorial()(নতুন 2.6)।


2
পাইথন সম্প্রদায়ের বিরাজমান মেজাজের সঠিক (আমার জ্ঞানের সেরাতম) অ্যাকাউন্টের জন্য +1 - যদিও আমি অবশ্যই এই ক্ষেত্রে বিরাজমান মেজাজের বিরুদ্ধে যেতে পছন্দ করি তবে তারা যেভাবেই হোক তার জন্য তাদের জানা ভাল। এছাড়াও, আমি এলটিইউর কাছ থেকে অসমর্থিত লিস্টারদের সম্পর্কে কিছুটা পছন্দ করি (আমি তাদের মধ্যে একজন হব, আমার ধারণা)। :-)
মাইশা মারকিজিক

7

এই উত্তরের উদ্দেশ্যটি হ'ল এমন একটি গণনা সরবরাহ করা যা নির্দিষ্ট পরিস্থিতিতে কার্যকর - যেমন যখন ক) প্রচুর পরিমাণে মানগুলি এমনভাবে বৃদ্ধি করা হয় যে চূড়ান্ত পণ্যটি খুব বড় বা চূড়ান্ত হতে পারে এবং খ) আপনি ডন করেন না ' টি সঠিক উত্তরটির বিষয়ে সত্যই যত্নশীল নয়, তার পরিবর্তে বেশ কয়েকটি ক্রম রয়েছে এবং প্রতিটিটির পণ্যের ভিত্তিতে সেগুলি অর্ডার করতে সক্ষম হতে চান।

আপনি যদি কোনও তালিকার উপাদানগুলিকে, যেখানে l তালিকার তালিকা তৈরি করতে চান তবে আপনি এটি করতে পারেন:

import math
math.exp(sum(map(math.log, l)))

এখন, সেই পদ্ধতির মতো পাঠযোগ্য নয়

from operator import mul
reduce(mul, list)

যদি আপনি এমন একজন গণিতবিদ হন যিনি হ্রাস () হ্রাস করার সাথে পরিচিত নন তবে বিপরীতটি সত্য হতে পারে তবে আমি সাধারণ পরিস্থিতিতে এটি ব্যবহার করার পরামর্শ দেব না। প্রশ্নটিতে উল্লিখিত পণ্য () ফাংশনের চেয়ে এটি কম পঠনযোগ্য (কমপক্ষে অ-গণিতবিদদের কাছে)।

তবে আপনি যদি এমন পরিস্থিতিতে থাকেন তবে যেখানে আপনি ভূগর্ভস্থ বা উপচে পড়া ঝুঁকির ঝুঁকি রাখেন in

>>> reduce(mul, [10.]*309)
inf

এবং আপনার উদ্দেশ্য হ'ল পণ্যগুলি কী তা তা জানার পরিবর্তে বিভিন্ন ক্রমের পণ্যগুলির তুলনা করা

>>> sum(map(math.log, [10.]*309))
711.49879373515785

যাবার উপায় হ'ল কারণ বাস্তব-জগতে সমস্যা হ্রাস করা কার্যত অসম্ভব যাতে আপনি এই পদ্ধতির সাথে উপচে পড়বেন বা নিমজ্জিত হবেন। (এই গণনার ফলাফল যত বড় হবে আপনি যদি এটি হিসাব করতে পারতেন তবে পণ্যটি তত বৃহত্তর হত ))


1
এটি চালাক, তবে আপনার যদি কোনও নেতিবাচক বা শূন্য মান থাকে তবে ব্যর্থ হয়। : /
অ্যালেক্স মেইবার্গ

7

আমি পারফপ্লট (আমার একটি ছোট প্রকল্প) এর সাথে বিভিন্ন সমাধান পরীক্ষা করেছি এবং এটি পেয়েছি

numpy.prod(lst)

এটি এখন পর্যন্ত সবচেয়ে দ্রুত সমাধান (যদি তালিকাটি খুব ছোট না হয়)।

এখানে চিত্র বর্ণনা লিখুন


প্লটটি পুনরুত্পাদন করার কোড:

import perfplot
import numpy

import math
from operator import mul
from functools import reduce

from itertools import accumulate


def reduce_lambda(lst):
    return reduce(lambda x, y: x * y, lst)


def reduce_mul(lst):
    return reduce(mul, lst)


def forloop(lst):
    r = 1
    for x in lst:
        r *= x
    return r


def numpy_prod(lst):
    return numpy.prod(lst)


def math_prod(lst):
    return math.prod(lst)


def itertools_accumulate(lst):
    for value in accumulate(lst, mul):
        pass
    return value


perfplot.show(
    setup=numpy.random.rand,
    kernels=[reduce_lambda, reduce_mul, forloop, numpy_prod, itertools_accumulate, math_prod],
    n_range=[2 ** k for k in range(15)],
    xlabel="len(a)",
    logx=True,
    logy=True,
)

2

আমি অবাক হয়েছি কারও itertools.accumulateসাথে এটি ব্যবহার করার পরামর্শ নেই operator.mul। এটি ব্যবহার করা এড়িয়ে যায় reduce, যা পাইথন 2 এবং 3 এর চেয়ে পৃথক ( functoolsপাইথন 3 এর জন্য প্রয়োজনীয় আমদানির কারণে ) এবং এরপরে তিনি নিজে গুয়েডো ভ্যান রসুম আন-পাইথোনিক হিসাবে বিবেচনা করেছেন :

from itertools import accumulate
from operator import mul

def prod(lst):
    for value in accumulate(lst, mul):
        pass
    return value

উদাহরণ:

prod([1,5,4,3,5,6])
# 1800

1

একটি বিকল্প ব্যবহার করা numbaএবং @jitবা @njitপ্রসাধক । আমি আপনার কোডটিতে একটি বা দুটি ছোট টুইটও করেছি (কমপক্ষে পাইথন 3 এ, "তালিকা" একটি মূলশব্দ যা কোনও চলক নামের জন্য ব্যবহার করা উচিত নয়):

@njit
def njit_product(lst):
    p = lst[0]  # first element
    for i in lst[1:]:  # loop over remaining elements
        p *= i
    return p

সময়সীমার উদ্দেশ্যে, প্রথমে নাম্বার ব্যবহার করে ফাংশনটি সংকলন করতে আপনাকে একবার চালানো দরকার। সাধারণভাবে, ফাংশনটি প্রথমবার বলা হয়ে সংকলিত হবে এবং তারপরে মেমরি থেকে কল করা হবে (দ্রুত)।

njit_product([1, 2])  # execute once to compile

এখন আপনি যখন আপনার কোডটি কার্যকর করবেন, এটি ফাংশনের সংকলিত সংস্করণ দিয়ে চলবে। আমি তাদেরকে একটি জুপির নোটবুক এবং %timeitযাদু ফাংশন ব্যবহার করে সময়সাপেক্ষ করেছি :

product(b)  # yours
# 32.7 µs ± 510 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

njit_product(b)
# 92.9 µs ± 392 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

নোট করুন যে আমার মেশিনে পাইথন ৩.৩ চালাচ্ছেন, নেটিভ পাইথন forলুপটি আসলে দ্রুততম ছিল। জুপিটার নোটবুক এবং %timeitম্যাজিক ফাংশন সহ নম্বা-সজ্জিত পারফরম্যান্স পরিমাপ করার ক্ষেত্রে এখানে একটি কৌশল থাকতে পারে । আমি নিশ্চিত যে উপরের সময়গুলি সঠিক কিনা, তাই আমি আপনার সিস্টেমে চেষ্টা করে দেখতে চেষ্টা করব এবং নাম্বা আপনাকে একটি পারফরম্যান্স উত্সাহ দেয় কিনা তা দেখার পরামর্শ দিই।


0

আমি খুঁজে পাওয়া সবচেয়ে দ্রুততম উপায়টি ছিল:

mysetup = '''
import numpy as np
from find_intervals import return_intersections 
'''

# code snippet whose execution time is to be measured
mycode = '''

x = [4,5,6,7,8,9,10]
prod = 1
i = 0
while True:
    prod = prod * x[i]
    i = i + 1
    if i == len(x):
        break
'''

# timeit statement for while:
print("using while : ",
timeit.timeit(setup=mysetup,
              stmt=mycode))

# timeit statement for mul:
print("using mul : ",
    timeit.timeit('from functools import reduce;
    from operator import mul;
    c = reduce(mul, [4,5,6,7,8,9,10])'))

# timeit statement for mul:
print("using lambda : ",      
    timeit.timeit('from functools import reduce;
    from operator import mul;
    c = reduce(lambda x, y: x * y, [4,5,6,7,8,9,10])'))

এবং সময়গুলি হল:

>>> using while : 0.8887967770060641

>>> using mul : 2.0838719510065857

>>> using lambda : 2.4227715369997895

এটি সম্ভবত তালিকাটির সংক্ষিপ্ত দৈর্ঘ্যের কারণে সম্ভবত আরও কিছু পরীক্ষার প্রয়োজন রয়েছে
ক্রেমিকেল

0

অপির পরীক্ষার জন্য পাইথন 3 ফলাফল: (প্রত্যেকের জন্য 3 টির মধ্যে সেরা)

with lambda: 18.978000981995137
without lambda: 8.110567473006085
for loop: 10.795806062000338
with lambda (no 0): 26.612515013999655
without lambda (no 0): 14.704098362999503
for loop (no 0): 14.93075215499266

-4

এটি এর প্রতারণা করার পরেও কাজ করে

def factorial(n):
    x=[]
    if n <= 1:
        return 1
    else:
        for i in range(1,n+1): 
            p*=i
            x.append(p)
        print x[n-1]    

আমি ইন্ডেন্টেশনটি ঠিক করেছি, তবে আমি মনে করি আপনার শেষেরটি প্রতিস্থাপনের printসাথে প্রতিস্থাপন করা উচিত । এছাড়াও, তালিকায় অন্তর্বর্তী মানগুলি সংরক্ষণ করার দরকার নেই, আপনাকে কেবল pবেটউইন পুনরাবৃত্তিগুলি সংরক্ষণ করতে হবে।
বোপ্পেএইচ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.