列表中对的乘积之和

use*_*144 8 python numpy python-itertools pandas

这是我的问题.给出一个清单

xList = [9, 13, 10, 5, 3]
Run Code Online (Sandbox Code Playgroud)

我想计算每个元素的总和乘以后续元素

sum([9*13, 9*10, 9*5 , 9*3]) + 
sum([13*10, 13*5, 13*3]) + 
sum([10*5, 10*3]) + 
sum ([5*3])
Run Code Online (Sandbox Code Playgroud)

在这种情况下,答案是608.

有没有办法做到这一点或许itertools本地numpy

以下是我提出的功能.它完成了这项工作,但它远非理想,因为我想添加其他东西.

    def SumProduct(xList):
        ''' compute the sum of the product 
        of a list 
        e.g. 
        xList = [9, 13, 10, 5, 3]
        the result will be 
        sum([9*13, 9*10, 9*5 , 9*3]) + 
        sum([13*10, 13*5, 13*3]) + 
        sum([10*5, 10*3]) + 
        sum ([5*3])
        '''
        xSum = 0
        for xnr, x in enumerate(xList):
            #print xnr, x
            xList_1 = np.array(xList[xnr+1:])
            #print x * xList_1
            xSum = xSum + sum(x * xList_1)
        return xSum
Run Code Online (Sandbox Code Playgroud)

任何帮助赞赏.

注意:如果你想知道,我正在尝试用熊猫实现Krippendorf的alpha

use*_*ica 25

x = array([9, 13, 10, 5, 3])
result = (x.sum()**2 - x.dot(x)) / 2
Run Code Online (Sandbox Code Playgroud)

与其他可能具有二次性能的解决方案相比,这利用了一些数学简化来在线性时间和恒定空间中工作.

这是一个如何工作的图表.假设x = array([2, 3, 1]).然后,如果您将产品视为矩形区域:

x is this stick: -- --- -

x.sum()**2 is this rectangle:
   -- --- -
  |xx xxx x
  |xx xxx x

  |xx xxx x
  |xx xxx x
  |xx xxx x

  |xx xxx x

x.dot(x) is this diagonal bit:
   -- --- -
  |xx
  |xx

  |   xxx
  |   xxx
  |   xxx

  |       x

(x.sum()**2 - x.dot(x)) is the non-diagonal parts:
   -- --- -
  |   xxx x
  |   xxx x

  |xx     x
  |xx     x
  |xx     x

  |xx xxx

and (x.sum()**2 - x.dot(x)) / 2 is the product you want:
   -- --- -
  |   xxx x
  |   xxx x

  |       x
  |       x
  |       x

  |
Run Code Online (Sandbox Code Playgroud)

  • 另一种了解其工作原理的方法:从总和的平方开始,说(a + b + c + d)^ 2.这扩展到有一大堆术语(把它放到WolframAlpha看看).我们想要除了那些只有元素平方的项之外的所有项,所以需要减去这些项.其余的条款都乘以2,所以除以这个,我们就得到了我们想要的东西. (5认同)
  • 很好,因为线性. (3认同)
  • 神圣的bejezes.数学有时非常有用,对吧? (2认同)
  • @PadraicCunningham:我试图制作一些ASCII艺术图表.他们有帮助吗? (2认同)

Pad*_*ham 7

你真的想要组合而不是产品:

from itertools import combinations

print(sum(a*b for a,b in combinations(xList,2)))
608
Run Code Online (Sandbox Code Playgroud)

即使从python列表创建一个numpy数组,@ user2357112 回答也会与我们其他人擦肩而过.

In [38]: timeit sum(a*b for a,b in combinations(xlist,2))
10000 loops, best of 3:
89.7 µs per loop

In [40]: timeit sum(mul(*t) for t in itertools.combinations(xlist, 2))
1000 loops, best of 3:
165 µs per loop

In [41]: %%timeit                                        
x = array(arr)
(x.sum()**2 - (x**2).sum()) / 2
   ....: 
100000 loops, best of 3:
 10.9 µs per loop

In [42]: timeit np.triu(np.outer(x, x), k=1).sum()
10000 loops, best of 3:
48.1 µs per loop
In [59]: %%timeit
....: xarr = np.array(xList)
....: N = xarr.size
....: range1 = np.arange(N)
....: mask = range1[:,None] < range1
....: out = ((mask*xarr)*xarr[:,None]).sum()
10000 loops, best of 3: 30.4 µs per loop
Run Code Online (Sandbox Code Playgroud)

所有列表/数组都有50个元素.

从user2357112窃取逻辑并在sum python的普通列表中使用它非常有效:

In [63]: timeit result = (sum(xList)**2 - sum(x ** 2 for x in xList)) / 2
100000 loops, best of 3: 
4.63 µs per loop
Run Code Online (Sandbox Code Playgroud)

但对于大型阵列而言,numpy解决方案仍然要快得多.


War*_*ser 6

这是一种方式:

In [14]: x = [9, 13, 10, 5, 3]

In [15]: np.triu(np.outer(x, x), k=1).sum()
Out[15]: 608
Run Code Online (Sandbox Code Playgroud)

但我会选择@ user2357112的答案.