I want to sum the products of all distinct pairs in a list. I wrote the following code that counts correctly this: 1*2 + 1*3 + 1*4 + 2*3 + 2*4 + 3*4
l = [1, 2, 3, 4]
def sum_of_pairs(ls):
return sum([x * y for x in ls for y in ls[ls.index(x) + 1:]])
print(sum_of_pairs(l))
When I try to change list to l = [1, 1, 1, 1]
it returns 12 (and not 6).
Why is this happening?
The immediate issue is that you are using ls.index
to find where to start the inner loop. list.index
returns the index of the first matching item, so will only do what you want if there are no duplicates in the list. Another problem is that it performs a linear search of your list for every iteration of the outer loop, making your algorithm needlessly inefficient.
A number of workarounds are available. A simple one is using enumerate
to follow along with the index that you want:
sum(n * ls[j] for i, n in enumerate(ls) for j in range(i + 1, len(ls)))
Or you could use a pair of range
objects:
sum(ls[i] * ls[j] for i in range(len(ls)) for j in range(i + 1, len(ls)))
Creating a range
is generally cheaper than copying out the entire sublist every time, as with
sum(x * y for i, x in enumerate(ls) for y in ls[i + 1:])
Alternatively, you could use itertools.combinations
to generate the values for you a bit more efficiently:
sum(x * y for x, y in itertools.combinations(ls, 2))
Instead, use the following short approach with itertools.starmap
and itertools.combinations
features:
from itertools import starmap, combinations
from operator import mul
def sum_of_pairs(lst):
return sum(starmap(mul, combinations(lst, 2)))
print(sum_of_pairs([1, 2, 3, 4])) # 35
print(sum_of_pairs([1, 1, 1, 1])) # 6
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.