开发者

Multiplying a subset of a list of integers together in python

Let's say I have a list of 10 integers and I want the result of multiplying the 开发者_StackOverflow中文版first 5 together. Is there a pythonic way of doing this? Python seems to be great with lists :)


import operator
l = [1, 2, 3, 4, 5, 6, 7, 8, 9]

print reduce(operator.mul, [v for (k, v,) in enumerate(l) if k < 5])
>> 120

Edit: Better way to do it

print reduce(operator.mul, l[:5])
>> 120


Lot's of ways. Here's one:

>>> a = range(1,10)
>>> reduce(lambda x,y: x*y, a[:5])
120


When there are many ways to do something, I turn to criteria such as readability or speed to decide which code to use. Here is some code which suggests that use_loop and use_reduce are roughly tied in terms of speed (at least for the values tested!)

import operator
import itertools

a=range(1,1000)
def use_loop(a,n):
    result=1
    for num in a[:n]:
        result*=num
    return result

def use_reduce(a,n):
    return reduce(operator.mul, a[:n])

def use_reduce_lambda(a,n):
    return reduce(lambda x,y: x*y, a[:n])

def use_islice_loop(a,n):
    result=1
    for num in itertools.islice(a,n):
        result*=num
    return result

def use_islice_reduce(a,n):
    return reduce(operator.mul, itertools.islice(a,n))

if __name__=='__main__':
    n=50
    print(use_loop(a,n))
    print(use_reduce(a,n))
    print(use_reduce_lambda(a,n))    
    print(use_islice_loop(a,n))
    print(use_islice_reduce(a,n))    

Here are the timing results:

% python -mtimeit -s"import test" "test.use_loop(test.a,50)"
10000 loops, best of 3: 16.1 usec per loop
% python -mtimeit -s"import test" "test.use_reduce(test.a,50)"
100000 loops, best of 3: 16.3 usec per loop
% python -mtimeit -s"import test" "test.use_islice_loop(test.a,50)"
10000 loops, best of 3: 19.6 usec per loop
% python -mtimeit -s"import test" "test.use_islice_reduce(test.a,50)"
10000 loops, best of 3: 19.2 usec per loop
% python -mtimeit -s"import test" "test.use_reduce_lambda(test.a,50)"
10000 loops, best of 3: 32.1 usec per loop

At least for the value of a (1000) and n (50) tested, itertools.islice did not seem to help performance. use_reduce_lambda was significantly slower than it's cousin use_reduce, which used operator.mul. The time required to import operator was not included in the test, however.

Since use_loop and use_reduce seem equally fast, I'd suggest using reduce since its short, idiomatic code should be quite readable to most python programmers. However, in matters of taste I don't think it pays to be too opinionated. Choose what you like best, just be consistent.

PS. As of Python 3+, reduce is no longer a built-in function, but can be accessed through functools.reduce.


Using reduce:

reduce(lambda x, y: x*y, mylist[:5])

e.g.,

>>> reduce(lambda x,y:x*y, range(1,5))
24

the reduce() function applies the given function (here, multiplication) over the first two items of the list, hereby reducing them to one item. This is done until there is only one item in the list. This item is returned as the result. This notation is derived from functional languages.

Iterating through the list:

result=1
for i in mylist[:5]:
    result*=i

e.g,

>>> result=1
>>> for i in range(1,5):
    result*=i
>>> result
24

This is the most general way of aggregating some function over all items of a list; It is similar to the way this would have been done Java or C.


This is a simple function that will do what you want.

def multiply(args):
    x= 1
    for arg in args:
       x*= arg
    return x

l = [1, 2, 3, 4, 5, 6, 7, 8, 9]

multiply(l)
>>>362880
multiply(l[:5])
>>>120
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜