我想在列表中找出夫妻产品的总和。
例如,列表被赋予[1, 2, 3, 4]
。我想得的是answer = 1*2 + 1*3 + 1*4 + 2*3 + 2*4 + 3*4
。
我使用暴力破解,它为非常大的列表提供了超时错误。 我想要一种有效的方法来做到这一点。请告诉我,我该怎么做?
这是我的代码,这是有效的,但我需要更高效的代码:
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
答案 0 :(得分:6)
这是:
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的方法和我的
的表现结果和测试代码如下(使用的时间越少越好):
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])
答案 1 :(得分:3)
使用itertools.combinations
生成唯一对:
# 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获取每对的产品:
products = [x*y for x, y in unique_pairs] # => [2, 3, 4, 6, 8, 12]
然后使用sum
添加您的产品:
answer = sum(products) # => 35
这可以全部包含在单行中,如下所示:
answer = sum(x*y for x,y in itertools.combinations([1, 2, 3, 4], 2))
在使其成为单行时,使用combinations
的结果而不会转换为list
。此外,列表理解周围的括号将被丢弃,转换为generator expression。
注意:Eastsun's answer和georg's answer使用更好的算法,并且很容易超出我对大型列表的回答。
答案 2 :(得分:1)
注意:实际上@Eastsun's answer更好。
这是另一个,更多"算法"处理这个问题的方法。观察给定的
0 , 1 ,..., n
所需的金额是(由于分配法)
a 0 ( 1 + a 2 + ... + a n ) + a 1 (a 2 + a 3 + ... + a n ) + ... + a n-2 ( n-1 + a n ) + a n-1 a n
导致以下算法:
sum
为0,current
为最后一个元素sum
和current
相乘并添加到结果current
添加到sum
current
成为current
在python中:
sum = 0
res = 0
cur = len(given) - 1
while cur >= 0:
res += given[cur] * sum
sum += given[cur]
cur -= 1
print res
答案 3 :(得分:0)
如果没有外部库,您可以使用map
和lambda
成对计算*
,然后sum
一切
l=[1, 2, 3, 4]
sum(map(lambda x,y:x*y, l, l[1:]+[l[0]]))
但是既然你正在处理大数据,我建议你使用numpy。
import numpy as np
l = np.array([1, 2, 3, 4])
print sum(l*np.roll(l, 1))
# 24
编辑:跟上OP的更新问题
import numpy as np
l = [1, 2, 3, 4]
sums = 0
while l:
sums+=sum(l.pop(0)*np.array(l))
print sums
#35
所以它的作用是取出列表的第一个元素,其余部分取出*
。重复直到列表中没有任何内容可以取出。
答案 4 :(得分:0)
def sumOfProductsOfCouples(l): 返回总和(l [i-1] * l [i]为i,n为枚举(l))
答案 5 :(得分:0)
from itertools import combinations
l=[1, 2, 3, 4]
cnt=0
for x in combinations(l,2):
cnt+=x[0]*x[1]
print (cnt)
输出;
>>>
35
>>>
combinations()
会按照您的意愿给出你的对子。然后做你的计算。
调试;
l=[1, 2, 3, 4]
for x in combinations(l,2):
print (x)
>>>
(1, 2)
(1, 3)
(1, 4)
(2, 3)
(2, 4)
(3, 4)
>>>
看到你的配对在这里。实际上你会找到这个combinations pairs.
答案 6 :(得分:0)
使用permutations
模块中的itertools
方法:
from itertools import *
p = permutations([1, 2, 3, 4], 2) # generate permutations of two
p = [frozenset(sorted(i)) for i in p] # sort items and cast
p = [list(i) for i in set(p)] # remove duplicates, back to lists
total = sum([i[0] * i[1] for i in p]) # 35 your final answer
答案 7 :(得分:0)
你可以使用map,sum函数。
>>> a = [1, 2, 3, 4]
>>> sum(map(sum, [map(lambda e: e*k, l) for k, l in zip(a, (a[start:] for start, _ in enumerate(a, start=1) if start < len(a)))]))
35
将上面的表达式划分为部分,
>>> a = [1, 2, 3, 4]
>>> c = (a[start:] for start, _ in enumerate(a, start=1) if start < len(a))
>>> sum(map(sum, [map(lambda e: e*k, l) for k, l in zip(a, c)]))
35