Reputation: 31
In python I have a list of strings that are digits. I have a nested for loop to go through it and sum each digit. Is there a way to do this in a list comprehension? Below I have the loop that works and a list comprehension that doesnt work.
num_sum should = 1 + 1 + 8 + 9
number_list = ["1", "18", "9"]
for i in number_list:
for j in i:
num_sum += int(j)
# thing = [num_sum += int(j) for i in number_list for j in i]
Upvotes: 1
Views: 1927
Reputation: 31354
This is what you're after, I think?
thing = sum(int(n) for n in number_list)
Note: this is effectively a generator, there's no need to put the numbers in a list and then sum them, which is why you don't see []
inside the parentheses of the call to sum()
.
Or from your example it looks like you actually want to sum the individual digits:
thing = sum(int(d) for n in number_list for d in n)
To answer your question whether you can put a +=
operator in a list comprehension - you could, but it has no return value itself for all types. +=
assigns to the expression before the operator, but that assignment itself may or may not have a return value, which would get added to the list you're building in the comprehension. In most cases, that's not what you're after.
@ShadowRanger suggested the solution proposed by @yyforbidden may be faster - it is, in fact:
import random
from timeit import timeit
number_list = [str(random.randint(1, 100)) for _ in range(100)]
def comprehension():
return sum(int(d) for n in number_list for d in n)
def joined():
return sum(int(d) for d in ''.join(number_list))
assert comprehension() == joined()
print(timeit(comprehension, number=10000))
print(timeit(joined, number=10000))
Result:
0.4073738
0.3616424
I'd still prefer the comprehension because it more literally states what is going on and readable code is often preferable to performing code - but your needs may differ.
Upvotes: 3
Reputation: 159
No you cannot. That's a syntax error.
You can do the following instead:
number_list = ["1", "18", "9"]
num_sum = sum(int(i) for i in ''.join(number_list))
Upvotes: 2
Reputation: 155546
No, but in Python 3.2+ you can use itertools.accumulate
to achieve a similar effect, with chain
to flatten your list
of str
s of digits to an iterable of digits:
from itertools import accumulate, chain
thing = list(accumulate(map(int, chain.from_iterable(number_list))))
num_sum = thing[-1]
or if you don't actually need the list
:
num_sum = sum(map(int, chain.from_iterable(number_list)))
In 3.8+, the walrus operator, :=
, makes constructing the list
with a listcomp possible without accumulate
, though you can't use +=
, only explicit addition and reassignment, as :=
doesn't have an expression based +=
equivalent:
num_sum = 0
things = [(num_sum := num_sum + int(x)) for x in chain.from_iterable(number_list)]
# Chain not strictly necessary; could also do this though it would be a titch slower:
things = [(num_sum := num_sum + int(x)) for num in number_list for x in num]
Upvotes: 0