ฉันจะคูณทุกรายการในรายการพร้อมกับ Python ได้อย่างไร


204

ฉันต้องเขียนฟังก์ชั่นที่ใช้รายการตัวเลขและคูณเข้าด้วยกัน ตัวอย่าง: จะให้ฉัน[1,2,3,4,5,6] 1*2*3*4*5*6ฉันสามารถใช้ความช่วยเหลือของคุณจริงๆ

คำตอบ:


208

Python 3: ใช้functools.reduce:

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

Python 2: การใช้งานreduce:

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

สำหรับการเข้ากันได้กับการใช้ 2 และ 3 pip install sixแล้ว:

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

คุณไม่ได้นำเข้าโอเปอเรเตอร์ดังนั้นโซลูชันนี้มีขนาดเล็กกว่าเล็กน้อย ฉันสงสัยว่าเร็วกว่าไหน
j

30
@ โฮลด์: ฉันจับเวลาผลิตภัณฑ์โดยใช้ตัวเลขตั้งแต่ 1 ถึง 100 ทั้ง python2 และ 3 lambdaใช้ค่าเฉลี่ยของ. 02s / 1000 ซ้ำในขณะที่operator.mulใช้ค่าเฉลี่ยของ. 009s / 1,000 ซ้ำทำให้operator.mulลำดับความสำคัญเร็วขึ้น
whereswalden

4
@ คำว่าต่อไปอาจเป็นไปได้ว่าจะผ่านฟังก์ชั่นพิเศษ (แลมบ์ดา) เพิ่มค่าใช้จ่ายในขณะที่operator.mulตรงไปที่ซี
whereswalden

4
ฉันจะไม่เรียก. 009 ขนาดที่ต่ำกว่า. 02 เกือบครึ่งแล้ว
jlh

1
ในฐานะที่เป็นของงูใหญ่ 3.8 math.prod([1,2,3,4,5,6])ก็สามารถทำได้เพียงกับ (ต้องนำเข้าแน่นอน)
Tomerikoo

168

คุณสามารถใช้ได้:

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

ดูreduceและoperator.mulเอกสารประกอบสำหรับคำอธิบาย

คุณต้องการimport functoolsบรรทัดใน Python 3+


32
โปรดทราบว่าใน python3 reduce()ฟังก์ชั่นได้ถูกลบออกจาก namespace ส่วนกลางและวางไว้ในfunctoolsโมดูล ดังนั้นใน python3 from functools import reduceคุณจำเป็นต้องพูด
Eugene Yarmash

2
'1' เนื่องจากอาร์กิวเมนต์ที่สามนั้นไม่จำเป็นในกรณีนี้จำเป็นที่จะต้องมีอะไรบ้าง
wordoforthewise

5
@ คำพูดถัดไปโดยไม่มีอาร์กิวเมนต์ที่สามมันจะโยนข้อยกเว้น TypeError ถ้าคุณผ่านมันเป็นลำดับที่ว่างเปล่า
Francisco Couzo

1
lambda x,y: x*yยังใช้งานได้แทนoperator.mul

78

ฉันจะใช้numpy.prodเพื่อดำเนินการงาน ดูด้านล่าง

import numpy as np
mylist = [1, 2, 3, 4, 5, 6] 
result = np.prod(np.array(mylist))  

13
สะดวกสบายถ้าคุณใช้ Numpy อยู่แล้ว คุณอาจไม่จำเป็นต้องโยนมันเป็นรายการแรกสิ่งนี้น่าจะใช้ได้กับกรณีส่วนใหญ่result = np.prod(mylist)
Nick

4
สองสิ่งที่ต้องระวัง: 1)มันอาจล้นโดยเฉพาะอย่างยิ่งหากใช้ค่าเริ่มต้นnumpy.int32ตามด้านบน 2)สำหรับรายการขนาดเล็กสิ่งนี้จะช้าลงอย่างมีนัยสำคัญเนื่องจาก NumPy จำเป็นต้องจัดสรรอาร์เรย์ (เกี่ยวข้องหากซ้ำบ่อย)
ไม่แย้ม

1
ล้นสำหรับค่าที่สูงกว่า 21 ที่นี่np.prod(np.array(range(1,21)))
PatrickT

มันไม่ใช่ทางเลือกที่ดี สามารถล้นและช้าลง reduceความพยายาม
Peyman

57

หากคุณต้องการหลีกเลี่ยงการนำเข้าทุกอย่างและหลีกเลี่ยงพื้นที่ที่ซับซ้อนของ Python คุณสามารถใช้การวนรอบแบบง่าย

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

7
ข้อสังเกตเล็กน้อย: ตัวแบ่งส่วนใน Python นั้นง่ายมากและเนื่องจากเรากำลังจัดการกับ primitives ที่นี่เท่านั้นคุณสามารถหลีกเลี่ยง kludge ที่เริ่มต้นด้วย 1 โดยเริ่มจากรายการ [0] และวนซ้ำรายการ [1:] แม้ว่าการได้รับความสะดวกสบายกับคำตอบ 'ลด' ที่ทำงานได้มากขึ้นที่นี่มีคุณค่าในระยะยาวเพราะมันมีประโยชน์ในสถานการณ์อื่น ๆ
kungphu

@kungphu ผลิตภัณฑ์เปล่ามักจะถูกกำหนดเป็น 1 วิธีการแก้ปัญหาของคุณจะโยนข้อยกเว้นดัชนีข้อผิดพลาดแทนถ้าคุณผ่านมันลำดับที่ว่างเปล่า
Francisco Couzo

@ ฟรานซิสโกได้รับแล้ว แต่ฟังก์ชั่นนี้น่าจะทำให้เกิดข้อยกเว้นบางประการในกรณีนั้นเนื่องจากลำดับที่ว่างจะเป็นอินพุตที่ไม่ถูกต้องสำหรับฟังก์ชั่นนี้ อันที่จริงฟังก์ชันนี้ไม่มีความหมายสำหรับลำดับใด ๆ ที่มีค่าน้อยกว่าสองค่า หากคุณผ่านลำดับที่มีหนึ่งค่าและคูณด้วย 1 คุณจะต้องเพิ่มค่าที่ไม่ได้อยู่ที่นั่นซึ่งฉันจะบอกจำนวนพฤติกรรมที่ไม่คาดคิด
kungphu

1
@ kungphu พฤติกรรมของคำตอบนี้ถูกต้องคือการส่งรายการความยาว 1 ส่งคืนค่าและส่งรายการความยาว 0 คืน 1 มันอยู่ในแนวความคิดเดียวกันที่ให้ผลรวม ([]) เป็น 0 หรือผลรวม ([3]) เป็น 3. ดู: en.wikipedia.org/wiki/Empty_product
emorris

ฉันเห็นประเด็นของคุณเกี่ยวกับฟังก์ชันทางคณิตศาสตร์ อย่างไรก็ตามในสถานการณ์การพัฒนาที่ใช้งานได้จริงฉันจะเรียกมันว่าเป็นสถานการณ์ที่หายากมากซึ่งฟังก์ชั่นที่ตั้งใจจะใช้กับอินพุตควรส่งคืนค่าตามจำนวนที่ไม่มีอินพุตหรืออินพุตที่ไม่ถูกต้อง ฉันคิดว่ามันขึ้นอยู่กับเป้าหมายของแบบฝึกหัด: ถ้าเป็นเพียงการทำซ้ำไลบรารีมาตรฐานตกลงบางทีมันอาจสอนคนบางอย่างเกี่ยวกับวิธีการ (หรือ) ภาษาหรือสามารถใช้งานได้ มิฉะนั้นฉันจะบอกว่ามันพลาดโอกาสที่ดีในการให้บทเรียนเกี่ยวกับข้อโต้แย้งที่ถูกต้องและไม่ถูกต้อง
kungphu

14

เริ่มต้นPython 3.8เป็น.prodฟังก์ชั่นได้รับการรวมกับmathโมดูลในห้องสมุดมาตรฐาน:

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

วิธีการคืนค่าผลิตภัณฑ์ของstartค่า (ค่าเริ่มต้น: 1) คูณด้วยจำนวนซ้ำ:

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

>>> 720

หาก iterable ว่างเปล่าสิ่งนี้จะสร้างขึ้น1(หรือstartค่าถ้ามี)


10

นี่คือการวัดประสิทธิภาพจากเครื่องของฉัน มีความเกี่ยวข้องในกรณีนี้จะดำเนินการสำหรับอินพุตขนาดเล็กในลูปที่รันเป็นเวลานาน:

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}')

ผล:

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

คุณจะเห็นว่า Numpy นั้นค่อนข้างช้ากว่าอินพุตที่เล็กกว่าเนื่องจากมันจะจัดสรรอาร์เรย์ก่อนที่จะทำการคูณ นอกจากนี้ระวังการล้นใน Numpy


คุณสามารถเพิ่มวิธี evalเพิ่งออกมาจากความอยากรู้อยากเห็น
Mr_and_Mrs_D

ฉันสงสัยว่าmultiply_functoolsและmultiply_numpy มีน้ำหนักลดลงโดยไม่ต้องมองขึ้นnp, functoolsและoperatorGlobals ตามด้วยการค้นหาแอตทริบิวต์ คุณคิดจะเปลี่ยนไปใช้คนในท้องถิ่นหรือไม่ _reduce=functools.reduce, _mul = operator.mul` ในฟังก์ชั่นลายเซ็นแล้วreturn _reduce(_mul, iterable)ในร่างกาย ฯลฯ
Martijn Pieters

1
นอกจากนี้เวอร์ชัน numpy จะต้องแปลงตัวเลขให้เป็นอาร์เรย์ numpy ก่อน ปกติแล้วคุณได้ทำการแปลงแล้วการรวมไว้ในการกำหนดเวลานั้นไม่ยุติธรรมเลย ด้วยรายการที่ถูกแปลงเป็นอาเรย์ numpy หนึ่งครั้งnp.prod()ตัวเลือกจะเริ่มเร็วขึ้นที่ 100 องค์ประกอบหรือมากกว่า
Martijn Pieters

8

ฉันเองชอบสิ่งนี้สำหรับฟังก์ชั่นที่คูณองค์ประกอบทั้งหมดของรายการทั่วไปเข้าด้วยกัน:

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

มันกะทัดรัดใช้สิ่งง่าย ๆ (ตัวแปรและห่วงสำหรับ) และรู้สึกง่ายสำหรับฉัน (ดูเหมือนว่าฉันจะคิดปัญหาแค่เอามันคูณมันแล้วคูณต่อไปเรื่อย ๆ ! )


3
ดีมันง่ายและธรรมดาที่สุด
ghostkraviz

4
ทำไมไม่for i in n:แล้วtotal *= i? มันจะไม่ง่ายกว่านี้หรือ
Munim Munna

@MunimMunna มันไม่ได้ผลสำหรับฉันตามที่กล่าวมา
athul


3

Numpyมีprod()ฟังก์ชั่นที่ส่งคืนผลคูณของรายการหรือในกรณีนี้เนื่องจากมันมีค่าเป็นจำนวนมากมันเป็นผลคูณของอาร์เรย์เหนือแกนที่ระบุ:

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

... มิฉะนั้นคุณสามารถนำเข้าnumpy.prod():

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

2

พบคำถามนี้ในวันนี้ แต่ฉันสังเกตเห็นว่ามันไม่มีกรณีที่มีอยู่Noneในรายการ ดังนั้นทางออกที่สมบูรณ์จะเป็น:

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

ในกรณีของการเพิ่มเรามี:

print(reduce(lambda x, y: (x if x else 0) + (y if y else 0), a))

2
nums = str(tuple([1,2,3]))
mul_nums = nums.replace(',','*')
print(eval(mul_nums))

5
โปรดเพิ่มคำอธิบายลงในคำตอบของคุณ วิธีตอบ
xenteros

3
ฉันพูดสอดและพยายามอธิบายรหัส: ฉันชอบรหัสนี้มากเพราะใช้ eval ซึ่งตีความสตริงเป็นอาร์กิวเมนต์หรือฟังก์ชั่น (และโดยทั่วไปถือว่าเป็นสิ่งที่ไม่ปลอดภัยโดยเฉพาะเมื่อจัดการข้อมูลอินพุต ) บรรทัดก่อนหน้านั้นจะแทนที่เครื่องหมายจุลภาคที่คั่นทุกอันด้วยเครื่องหมายทวีคูณ*เช่นว่า eval จะรับรู้สิ่งนี้ว่าเป็นทวีคูณ ฉันสงสัยว่าประสิทธิภาพในการทำงานนี้เป็นอย่างไรเมื่อเปรียบเทียบกับโซลูชันอื่น ๆ
dennlinger

ว้าวช่างเป็นความคิดที่แย่!
โควาลสกี้

1

ฉันต้องการสิ่งนี้ในวิธีต่อไปนี้:

    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

1

นี่คือรหัสของฉัน:

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

ผล: ('1 * 1 * 2 * 3 * 4', 24)


0

ใช้การสอบถามซ้ำได้อย่างไร

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


-1

'' 'วิธีง่าย ๆ เพียงวิธีเดียวในการทำความเข้าใจตรรกะการใช้วนรอบ

Lap = [2,5,7,7,9] x = 1 สำหรับ i ใน Lap: x = i * x print (x)


คำตอบของคุณไม่ได้เพิ่มอะไรใหม่ในการอภิปรายของคำถามนี้
Sid

-3

มันง่ายมากไม่นำเข้าอะไร นี่คือรหัสของฉัน สิ่งนี้จะกำหนดฟังก์ชั่นที่ทวีคูณรายการทั้งหมดในรายการและส่งคืนผลิตภัณฑ์

def myfunc(lst):
    multi=1
    for product in lst:
        multi*=product
    return product

2
ทำซ้ำกับคำตอบของ DeadChex คำตอบของ piSHOCK คำตอบของ Shakti Nandan อย่าโพสต์คำตอบที่แนะนำไว้แล้ว
Munim Munna

มันควรกลับหลาย | - |
ลาร์ส
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.