Bagaimana saya bisa melipatgandakan semua item dalam daftar bersama dengan Python?

204

Saya perlu menulis fungsi yang mengambil daftar angka dan mengalikannya . Contoh: [1,2,3,4,5,6]akan memberi saya 1*2*3*4*5*6. Saya benar-benar bisa menggunakan bantuan Anda.

pengguna1897814
sumber

Jawaban:

208

Python 3: gunakan functools.reduce:

>>> from functools import reduce
>>> reduce(lambda x, y: x*y, [1,2,3,4,5,6])
720

Python 2: gunakan reduce:

>>> reduce(lambda x, y: x*y, [1,2,3,4,5,6])
720

Untuk kompatibel dengan penggunaan 2 dan 3 pip install six, maka:

>>> from six.moves import reduce
>>> reduce(lambda x, y: x*y, [1,2,3,4,5,6])
720
tingkat kaya
sumber
Anda tidak mengimpor operator, jadi solusi ini sedikit lebih kompak. Saya ingin tahu mana yang lebih cepat.
Diadili
30
@jheld: Saya menghitung waktu pembuatan angka dari 1 hingga 100. Dalam python2 dan 3, lambdamengambil rata-rata 0,02s / 1000 repetisi, sedangkan operator.mulmengambil rata-rata 0,009s / 1000 repetisi, membuat operator.mulurutan besarnya lebih cepat.
whereswalden
4
@wordsf mungkin juga itu yang melalui fungsi tambahan (lambda) menambahkan overhead, sedangkan operator.mullangsung ke C.
whereswalden
4
Saya benar-benar tidak akan memanggil 0,009 urutan besarnya lebih rendah dari 0,02. Hanya sekitar setengahnya.
jlh
1
Pada Python 3.8, itu bisa dilakukan dengan mudah math.prod([1,2,3,4,5,6]). (memerlukan impor tentu saja)
Tomerikoo
168

Kamu bisa memakai:

import operator
import functools
functools.reduce(operator.mul, [1,2,3,4,5,6], 1)

Lihat reducedan operator.muldokumentasi untuk penjelasan.

Anda memerlukan import functoolsbaris dalam Python 3+.

icecrime
sumber
32
Perhatikan bahwa dalam python3, reduce()fungsinya telah dihapus dari namespace global dan ditempatkan di functoolsmodul. Jadi, dalam python3 yang perlu Anda katakan from functools import reduce.
Eugene Yarmash
2
'1' sebagai argumen ketiga tidak diperlukan di sini, apa kasus di mana itu akan diperlukan?
kata
5
@ wordsterlalu tanpa argumen ketiga, ia melempar pengecualian TypeError jika Anda memberikan urutan kosong
Francisco Couzo
1
lambda x,y: x*yjuga berfungsi sebagai gantioperator.mul
79

Saya akan menggunakan numpy.produntuk melakukan tugas. Lihat di bawah.

import numpy as np
mylist = [1, 2, 3, 4, 5, 6] 
result = np.prod(np.array(mylist))  
belindanju
sumber
13
Nyaman jika Anda sudah menggunakan Numpy. Anda mungkin bahkan tidak perlu memasukkannya sebagai daftar terlebih dahulu, ini harus bekerja untuk sebagian besar kasusresult = np.prod(mylist)
Nick
4
Dua hal yang harus diperhatikan: 1) Mungkin meluap, terutama jika menggunakan default numpy.int32seperti di atas 2) Untuk daftar kecil ini akan jauh lebih lambat, karena NumPy perlu mengalokasikan array (relevan jika sering diulang)
Disenchanted
1
overflow untuk nilai di atas 21 di sininp.prod(np.array(range(1,21)))
PatrickT
Itu bukan pilihan yang baik. Itu bisa meluap dan lebih lambat. coba reduce.
Peyman
57

Jika Anda ingin menghindari mengimpor apa pun dan menghindari area Python yang lebih rumit, Anda bisa menggunakan simpel untuk loop

product = 1  # Don't use 0 here, otherwise, you'll get zero 
             # because anything times zero will be zero.
list = [1, 2, 3]
for x in list:
    product *= x
DeadChex
sumber
7
Catatan minor: Irisan dengan Python sangat mudah, dan karena kita hanya berurusan dengan primitif di sini, Anda dapat menghindari kludge minor mulai dengan 1 dengan mulai dengan daftar [0] dan beralih ke daftar [1:]. Meskipun merasa nyaman dengan jawaban 'pengurangan' yang lebih fungsional di sini bermanfaat dalam jangka panjang karena juga berguna dalam situasi lain.
kungphu
@ kungphu Produk kosong biasanya didefinisikan sebagai 1, solusi Anda akan melemparkan pengecualian IndexError sebagai gantinya jika Anda memberikannya urutan kosong
Francisco Couzo
@ Francisco Diberikan, tetapi fungsi ini mungkin harus memberikan beberapa rasa pengecualian dalam kasus itu, karena urutan kosong akan menjadi input yang tidak valid untuk fungsi ini. Bahkan, fungsi ini tidak berarti untuk urutan apa pun dengan kurang dari dua nilai; jika Anda melewati urutan dengan satu nilai dan mengalikannya dengan 1, pada dasarnya Anda telah menambahkan nilai yang tidak ada di sana, yang menurut saya sama dengan perilaku tak terduga.
kungphu
1
@ Kungphu, perilaku untuk jawaban ini benar, yaitu melewati daftar panjang 1 mengembalikan nilai, dan melewati daftar panjang 0 mengembalikan 1. Ini di garis pemikiran yang sama yang memberikan jumlah ([]) sebagai 0 atau jumlah ([3]) sebagai 3. Lihat: en.wikipedia.org/wiki/Empty_product
emorris
Saya mengerti maksud Anda tentang fungsi matematika. Namun, dalam situasi pengembangan praktis, saya akan menyebutnya situasi yang sangat langka di mana fungsi yang secara eksplisit dimaksudkan untuk beroperasi pada input harus mengembalikan nilai mengingat berapa jumlah input yang tidak ada atau input yang tidak valid. Saya kira itu tergantung pada tujuan latihan: Jika itu hanya untuk meniru perpustakaan standar, OK, mungkin itu mengajarkan orang sesuatu tentang bagaimana (atau a) bahasa itu atau dapat diimplementasikan. Kalau tidak, saya akan mengatakan itu melewatkan kesempatan yang baik untuk memberikan pelajaran tentang argumen yang valid dan tidak valid.
kungphu
14

Mulai Python 3.8, .prodfungsi telah dimasukkan ke mathmodul di perpustakaan standar:

math.prod(iterable, *, start=1)

Metode mengembalikan produk dari startnilai (default: 1) kali jumlah angka yang berulang:

import math
math.prod([1, 2, 3, 4, 5, 6])

>>> 720

Jika iterable kosong, ini akan menghasilkan 1(atau startnilainya, jika disediakan).

Xavier Guihot
sumber
10

Inilah beberapa pengukuran kinerja dari mesin saya. Relevan jika ini dilakukan untuk input kecil dalam loop yang berjalan lama:

import functools, operator, timeit
import numpy as np

def multiply_numpy(iterable):
    return np.prod(np.array(iterable))

def multiply_functools(iterable):
    return functools.reduce(operator.mul, iterable)

def multiply_manual(iterable):
    prod = 1
    for x in iterable:
        prod *= x

    return prod

sizesToTest = [5, 10, 100, 1000, 10000, 100000]

for size in sizesToTest:
    data = [1] * size

    timerNumpy = timeit.Timer(lambda: multiply_numpy(data))
    timerFunctools = timeit.Timer(lambda: multiply_functools(data))
    timerManual = timeit.Timer(lambda: multiply_manual(data))

    repeats = int(5e6 / size)
    resultNumpy = timerNumpy.timeit(repeats)
    resultFunctools = timerFunctools.timeit(repeats)
    resultManual = timerManual.timeit(repeats)
    print(f'Input size: {size:>7d} Repeats: {repeats:>8d}    Numpy: {resultNumpy:.3f}, Functools: {resultFunctools:.3f}, Manual: {resultManual:.3f}')

Hasil:

Input size:       5 Repeats:  1000000    Numpy: 4.670, Functools: 0.586, Manual: 0.459
Input size:      10 Repeats:   500000    Numpy: 2.443, Functools: 0.401, Manual: 0.321
Input size:     100 Repeats:    50000    Numpy: 0.505, Functools: 0.220, Manual: 0.197
Input size:    1000 Repeats:     5000    Numpy: 0.303, Functools: 0.207, Manual: 0.185
Input size:   10000 Repeats:      500    Numpy: 0.265, Functools: 0.194, Manual: 0.187
Input size:  100000 Repeats:       50    Numpy: 0.266, Functools: 0.198, Manual: 0.185

Anda dapat melihat bahwa Numpy sedikit lebih lambat pada input yang lebih kecil, karena ia mengalokasikan array sebelum multiplikasi dilakukan. Juga, hati-hati terhadap luapan di Numpy.

Kecewa
sumber
Anda bisa menambahkan cara eval hanya karena penasaran
Mr_and_Mrs_D
Saya menduga itu multiply_functoolsdan multiply_numpy terbebani dengan harus mencari np, functoolsdan operatorglobal, diikuti oleh pencarian atribut. Maukah Anda beralih ke penduduk lokal? _reduce=functools.reduce, _mul = operator.mul` dalam tanda tangan fungsi kemudian return _reduce(_mul, iterable)di tubuh, dll.
Martijn Pieters
1
Juga, versi numpy harus terlebih dahulu mengkonversi angka menjadi array numpy; Anda biasanya sudah melakukan konversi itu, untuk memasukkan bahwa dalam timing tidak benar-benar adil. Dengan daftar dikonversi ke array numpy sekali, np.prod()opsi mulai menjadi tercepat di 100 elemen atau lebih.
Martijn Pieters
8

Saya pribadi suka ini untuk fungsi yang mengalikan semua elemen daftar generik bersama:

def multiply(n):
    total = 1
    for i in range(0, len(n)):
        total *= n[i]
    print total

Ini kompak, menggunakan hal-hal sederhana (variabel dan for loop), dan terasa intuitif bagi saya (sepertinya saya memikirkan masalahnya, ambil satu, gandakan, lalu gandakan dengan yang berikutnya, dan seterusnya! )

pengguna5038135
sumber
3
hebat, ini yang paling sederhana dan paling sederhana.
ghostkraviz
4
Mengapa tidak for i in n:, maka total *= i? bukankah itu akan jauh lebih sederhana?
Munim Munna
@MunimMunnaIt tidak bekerja untuk saya seperti cara di atas.
athul
5

Cara sederhananya adalah:

import numpy as np
np.exp(np.log(your_array).sum())
XXinyue
sumber
10
bagaimana dengan hanyanp.prod(your_Array)
dashesy
3

Numpymemiliki prod()fungsi yang mengembalikan produk dari daftar, atau dalam hal ini karena numpy, itu adalah produk dari array di atas sumbu yang diberikan:

import numpy
a = [1,2,3,4,5,6]
b = numpy.prod(a)

... atau Anda dapat mengimpor numpy.prod():

from numpy import prod
a = [1,2,3,4,5,6]
b = prod(a)
Leo Igane
sumber
2

Menemukan pertanyaan ini hari ini tetapi saya perhatikan bahwa tidak ada kasus di mana ada Nonedalam daftar. Jadi, solusi lengkapnya adalah:

from functools import reduce

a = [None, 1, 2, 3, None, 4]
print(reduce(lambda x, y: (x if x else 1) * (y if y else 1), a))

Dalam hal penambahan, kami memiliki:

print(reduce(lambda x, y: (x if x else 0) + (y if y else 0), a))
Xxxo
sumber
2
nums = str(tuple([1,2,3]))
mul_nums = nums.replace(',','*')
print(eval(mul_nums))
M. Dickson
sumber
5
Silakan tambahkan beberapa penjelasan untuk jawaban Anda. Bagaimana Menjawab
xenteros
3
Saya berpadu dan mencoba menjelaskan kode: Saya pribadi suka kode ini tidak banyak, karena menggunakan eval, yang menafsirkan string sebagai argumen atau fungsi (dan dengan demikian secara umum dipandang sebagai hal yang tidak aman untuk dilakukan, terutama ketika menangani input data ). Baris sebelum itu menggantikan setiap koma pembatas dengan multiplicative *, sehingga eval akan mengenali ini sebagai multiplicative. Saya bertanya-tanya bagaimana kinerja ini, terutama dibandingkan dengan solusi lain
dennlinger
Wow, ide yang buruk!
Kowalski
1

Saya ingin ini sebagai berikut:

    def product_list(p):
          total =1 #critical step works for all list
          for i in p:
             total=total*i # this will ensure that each elements are multiplied by itself
          return total
   print product_list([2,3,4,2]) #should print 48
Shakti Nandan
sumber
1

Ini kode saya:

def product_list(list_of_numbers):
    xxx = 1
    for x in list_of_numbers:
        xxx = xxx*x
    return xxx

print(product_list([1,2,3,4]))

hasil: ('1 * 1 * 2 * 3 * 4', 24)

jackim
sumber
0

Bagaimana kalau menggunakan rekursi?

def multiply(lst):
    if len(lst) > 1:
        return multiply(lst[:-1])* lst[-1]
    else:
        return lst[0]
mtdkki
sumber
-1

Solusi saya:

def multiply(numbers):
    a = 1
    for num in numbers:
        a *= num
        return a

  pass
Dorian Vanzant
sumber
-1

'' 'satu-satunya metode sederhana untuk memahami penggunaan logika untuk loop' ''

Lap = [2,5,7,7,9] x = 1 untuk i di Lap: x = i * x cetak (x)

Sandeep Raturi
sumber
Jawaban Anda tidak menambahkan sesuatu yang baru pada diskusi pertanyaan ini.
Sid
-3

Sangat sederhana, jangan mengimpor apa pun. Ini kode saya. Ini akan menentukan fungsi yang mengalikan semua item dalam daftar dan mengembalikan produk mereka.

def myfunc(lst):
    multi=1
    for product in lst:
        multi*=product
    return product
Aditya
sumber
2
Gandakan untuk jawaban DeadChex, jawaban piSHOCK, jawaban Shakti Nandan. Jangan memposting jawaban yang sudah disarankan.
Munim Munna
itu juga harus mengembalikan multi | - |
Lars