首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >列表中对偶的乘积之和

列表中对偶的乘积之和
EN

Stack Overflow用户
提问于 2015-01-26 14:45:27
回答 7查看 367关注 0票数 0

我想在列表中找出情侣乘积的总和。例如,一个列表被赋予了[1, 2, 3, 4]。我想要得到的是answer = 1*2 + 1*3 + 1*4 + 2*3 + 2*4 + 3*4

我使用蛮力来做这件事,它给了我非常大列表的超时错误。我想要一种有效的方法来做这件事。请告诉我,我该怎么做?

这是我的代码,这是工作的,但我需要一个更有效的:

代码语言:javascript
复制
def proSum(list):
    count  = 0
    for i in range(len(list)- 1):
        for j in range(i + 1, len(list)):
            count +=  list[i] * list[j]
    return count
EN

回答 7

Stack Overflow用户

发布于 2015-01-26 16:40:46

这就是它:

代码语言:javascript
复制
In [1]: def prodsum(xs):
   ...:     return (sum(xs)**2 - sum(x*x for x in xs)) / 2
   ...: 

In [2]: prodsum([1, 2, 3, 4]) == 1*2 + 1*3 + 1*4 + 2*3 + 2*4 + 3*4
Out[2]: True

那就让xs = a1, a2, .., an

(a1+a2+...+an)^2 = 2(a1a2+a1a3+...+an-1an) + (a1^2+...+an^2)

所以我们有

a1a2+...+an-1an = {(a1+a2+...+an)^2 - (a1^2+...+an^2)}/2

将@georg的方法与mine的性能进行比较

结果和测试代码如下(时间越短越好):

代码语言:javascript
复制
In [1]: import timeit

In [2]: import matplotlib.pyplot as plt

In [3]: def eastsunMethod(xs):
   ...:     return (sum(xs)**2 - sum(x*x for x in xs)) / 2
   ...: 

In [4]: def georgMethod(given):
   ...:     sum = 0
   ...:     res = 0
   ...:     cur = len(given) - 1
   ...: 
   ...:     while cur >= 0:
   ...:         res += given[cur] * sum
   ...:         sum += given[cur]
   ...:         cur -= 1
   ...:     return res
   ...: 

In [5]: sizes = range(24)

In [6]: esTimes, ggTimes = [], []

In [7]: for s in sizes:
   ...:     t1 = timeit.Timer('eastsunMethod(xs)', 'from __main__ import eastsunMethod;xs=range(2**%d)' % s)
   ...:     t2 = timeit.Timer('georgMethod(xs)', 'from __main__ import georgMethod;xs=range(2**%d)' % s)
   ...:     esTimes.append(t1.timeit(8))
   ...:     ggTimes.append(t2.timeit(8))

In [8]: fig, ax = plt.subplots(figsize=(18, 6));lines = ax.plot(sizes, esTimes, 'r', sizes, ggTimes);ax.legend(lines, ['Eastsun', 'georg'], loc='center');ax.set_xlabel('size');ax.set_ylabel('time');ax.set_xlim([0, 23])
票数 6
EN

Stack Overflow用户

发布于 2015-01-26 15:03:03

使用itertools.combinations生成唯一对:

代码语言:javascript
复制
# gives [(1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)]
unique_pairs = list(itertools.combinations([1, 2, 3, 4], 2))

然后使用list comprehension来获得每对的乘积:

代码语言:javascript
复制
products = [x*y for x, y in unique_pairs] # => [2, 3, 4, 6, 8, 12]

然后使用sum添加您的产品:

代码语言:javascript
复制
answer = sum(products) # => 35

这一切都可以用一行代码来包装,如下所示:

代码语言:javascript
复制
answer = sum(x*y for x,y in itertools.combinations([1, 2, 3, 4], 2))

在使其成为一行程序时,无需强制转换为list,即可使用combinations的结果。此外,列表理解周围的括号被丢弃,将其转换为generator expression

注释Eastsun's answergeorg's answer使用更好的算法,并且很容易在大型列表中胜过我的答案。

票数 3
EN

Stack Overflow用户

发布于 2015-01-26 15:09:07

在没有外部库的情况下,您可以使用maplambda成对计算*,然后对所有内容执行sum

代码语言:javascript
复制
l=[1, 2, 3, 4]
sum(map(lambda x,y:x*y, l, l[1:]+[l[0]]))

但由于您正在处理大数据,我建议您使用numpy。

代码语言:javascript
复制
import numpy as np

l = np.array([1, 2, 3, 4])

print sum(l*np.roll(l, 1))
# 24

编辑:跟上最新的操作问题

代码语言:javascript
复制
import numpy as np

l = [1, 2, 3, 4]
sums = 0
while l:
    sums+=sum(l.pop(0)*np.array(l))

print sums
#35

所以它所做的就是去掉list和*的第一个元素,剩下的元素。重复操作,直到列表中没有要删除的内容。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28145730

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档