简体   繁体   中英

Sum of products of all pairs in a list

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM