How to emulate sum() using a list comprehension?
Question:
Is it possible to emulate something like sum() using list comprehension ?
For example – I need to calculate the product of all elements in a list :
list = [1, 2, 3]
product = [magic_here for i in list]
#product is expected to be 6
Code that is doing the same :
def product_of(input):
result = 1
for i in input:
result *= i
return result
Answers:
>>> from functools import reduce
>>> from operator import mul
>>> nums = [1, 2, 3]
>>> reduce(mul, nums)
6
Python 3 Hack
In regards to approaches such as [total := total + x for x in [1, 2, 3, 4, 5]]
This is a terrible idea. The general idea of emulate sum()
using a list comprehension goes against the whole purpose of a list comprehension. You should not use a list comprehension in this case.
In Python 2.5
/ 2.6
You could use vars()['_[1]']
to refer to the list comprehension currently under construction. This is horrible and should never be used but it’s the closest thing to what you mentioned in the question (using a list comp to emulate a product).
>>> nums = [1, 2, 3]
>>> [n * (vars()['_[1]'] or [1])[-1] for n in nums][-1]
6
No; a list comprehension produces a list that is just as long as its input. You will need one of Python’s other functional tools (specifically reduce()
in this case) to fold the sequence into a single value.
List comprehension always creates another list, so it’s not useful in combining them (e.g. to give a single number). Also, there’s no way to make an assignment in list comprehension, unless you’re super sneaky.
The only time I’d ever see using list comprehensions as being useful for a sum method is if you only want to include specific values in the list, or you don’t have a list of numbers:
list = [1,2,3,4,5]
product = [i for i in list if i % 2 ==0] # only sum even numbers in the list
print sum(product)
or another example”:
# list of the cost of fruits in pence
list = [("apple", 55), ("orange", 60), ("pineapple", 140), ("lemon", 80)]
product = [price for fruit, price in list]
print sum(product)
Super sneaky way to make an assignment in a list comprehension
dict = {"val":0}
list = [1, 2, 3]
product = [dict.update({"val" : dict["val"]*i}) for i in list]
print dict["val"] # it'll give you 6!
…but that’s horrible 🙂
>>> reduce(int.__mul__,[1,2,3])
6
C:UsersHenry>python -m timeit -s "" "reduce(int.__mul__,range(10000))"
1000 loops, best of 3: 910 usec per loop
C:UsersHenry>python -m timeit -s "from operator import mul" "reduce(mul,range(10000))"
1000 loops, best of 3: 399 usec per loop
C:UsersHenry>
Something like this:
>>> a = [1,2,3]
>>> reduce(lambda x, y: x*y, a)
6
Found the magic on http://code.activestate.com/recipes/436482/.
>>> L=[2, 3, 4]
>>> [j for j in [1] for i in L for j in [j*i]][-1]
24
It should be the logic like the following code.
L=[2, 3, 4]
P=[]
for j in [1]:
for i in L:
for j in [j*i]:
P.append(j)
print(P[-1])
I complement the answer of Ignacio Vazquez-Abrams with some code that uses the reduce
operator of Python.
list_of_numbers = [1, 5, 10, 100]
reduce(lambda x, y: x + y, list_of_numbers)
which can also be written as
list_of_numbers = [1, 5, 10, 100]
def sum(x, y):
return x + y
reduce(sum, list_of_numbers)
Bonus: Python provides this functionality in the built-in sum
function. This is the most readable expression imo.
list_of_numbers = [1, 5, 10, 100]
sum(list_of_numbers)
It is possible to achieve by using lambda with list comprehension
Since we can’t assign a value in list comprehension we go with lambda
Solution:
>>> (lambda number_list, sum=0:[sum for number in number_list for sum in [sum + number]][-1])([1, 2, 3, 4, 5])
>>> 15
Starting in Python 3.8
, and the introduction of assignment expressions (PEP 572) (:=
operator), we can use and increment a variable within a list comprehension and thus reduce a list to the sum of its elements:
total = 0
[total := total + x for x in [1, 2, 3, 4, 5]]
# total = 15
This:
- Initialises a variable
total
to 0
- For each item,
total
is incremented by the current looped item (total := total + x
) via an assignment expression
I might be a bit late for this discussion, but I would like to mention that list comprehentions are turing complete, and thus this can be done with a list comprehention!
This however is messy, so I have used the following trick, which makes a cummulative array, and returns the last element
def sum(l):
return [c[-1] for c in [[0]] for e in l if c.append(c[-1] + e) is None][-1]
nums=[10,20,30,40,50]
total=sum(num for num in nums)
print(total) # You get 150 in total
Is it possible to emulate something like sum() using list comprehension ?
For example – I need to calculate the product of all elements in a list :
list = [1, 2, 3]
product = [magic_here for i in list]
#product is expected to be 6
Code that is doing the same :
def product_of(input):
result = 1
for i in input:
result *= i
return result
>>> from functools import reduce
>>> from operator import mul
>>> nums = [1, 2, 3]
>>> reduce(mul, nums)
6
Python 3 Hack
In regards to approaches such as [total := total + x for x in [1, 2, 3, 4, 5]]
This is a terrible idea. The general idea of emulate sum()
using a list comprehension goes against the whole purpose of a list comprehension. You should not use a list comprehension in this case.
In Python 2.5
/ 2.6
You could use vars()['_[1]']
to refer to the list comprehension currently under construction. This is horrible and should never be used but it’s the closest thing to what you mentioned in the question (using a list comp to emulate a product).
>>> nums = [1, 2, 3]
>>> [n * (vars()['_[1]'] or [1])[-1] for n in nums][-1]
6
No; a list comprehension produces a list that is just as long as its input. You will need one of Python’s other functional tools (specifically reduce()
in this case) to fold the sequence into a single value.
List comprehension always creates another list, so it’s not useful in combining them (e.g. to give a single number). Also, there’s no way to make an assignment in list comprehension, unless you’re super sneaky.
The only time I’d ever see using list comprehensions as being useful for a sum method is if you only want to include specific values in the list, or you don’t have a list of numbers:
list = [1,2,3,4,5]
product = [i for i in list if i % 2 ==0] # only sum even numbers in the list
print sum(product)
or another example”:
# list of the cost of fruits in pence
list = [("apple", 55), ("orange", 60), ("pineapple", 140), ("lemon", 80)]
product = [price for fruit, price in list]
print sum(product)
Super sneaky way to make an assignment in a list comprehension
dict = {"val":0}
list = [1, 2, 3]
product = [dict.update({"val" : dict["val"]*i}) for i in list]
print dict["val"] # it'll give you 6!
…but that’s horrible 🙂
>>> reduce(int.__mul__,[1,2,3])
6
C:UsersHenry>python -m timeit -s "" "reduce(int.__mul__,range(10000))"
1000 loops, best of 3: 910 usec per loop
C:UsersHenry>python -m timeit -s "from operator import mul" "reduce(mul,range(10000))"
1000 loops, best of 3: 399 usec per loop
C:UsersHenry>
Something like this:
>>> a = [1,2,3]
>>> reduce(lambda x, y: x*y, a)
6
Found the magic on http://code.activestate.com/recipes/436482/.
>>> L=[2, 3, 4]
>>> [j for j in [1] for i in L for j in [j*i]][-1]
24
It should be the logic like the following code.
L=[2, 3, 4]
P=[]
for j in [1]:
for i in L:
for j in [j*i]:
P.append(j)
print(P[-1])
I complement the answer of Ignacio Vazquez-Abrams with some code that uses the reduce
operator of Python.
list_of_numbers = [1, 5, 10, 100]
reduce(lambda x, y: x + y, list_of_numbers)
which can also be written as
list_of_numbers = [1, 5, 10, 100]
def sum(x, y):
return x + y
reduce(sum, list_of_numbers)
Bonus: Python provides this functionality in the built-in sum
function. This is the most readable expression imo.
list_of_numbers = [1, 5, 10, 100]
sum(list_of_numbers)
It is possible to achieve by using lambda with list comprehension
Since we can’t assign a value in list comprehension we go with lambda
Solution:
>>> (lambda number_list, sum=0:[sum for number in number_list for sum in [sum + number]][-1])([1, 2, 3, 4, 5])
>>> 15
Starting in Python 3.8
, and the introduction of assignment expressions (PEP 572) (:=
operator), we can use and increment a variable within a list comprehension and thus reduce a list to the sum of its elements:
total = 0
[total := total + x for x in [1, 2, 3, 4, 5]]
# total = 15
This:
- Initialises a variable
total
to0
- For each item,
total
is incremented by the current looped item (total := total + x
) via an assignment expression
I might be a bit late for this discussion, but I would like to mention that list comprehentions are turing complete, and thus this can be done with a list comprehention!
This however is messy, so I have used the following trick, which makes a cummulative array, and returns the last element
def sum(l):
return [c[-1] for c in [[0]] for e in l if c.append(c[-1] + e) is None][-1]
nums=[10,20,30,40,50]
total=sum(num for num in nums)
print(total) # You get 150 in total