【问题标题】:sum of products of couples in a list列表中夫妻的产品总和
【发布时间】:2015-01-26 06:45:27
【问题描述】:

我想找出列表中情侣产品的总和。 例如,给定一个列表[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

【问题讨论】:

  • 你想要相邻对的乘积(最后一个环绕)?
  • 请将您当前的代码添加到问题中
  • @lavee_singh,如果您编辑或更改有根本差异的问题,如果您输入 EDITED/UPDATED 关键字并保持原始要求不变,那就太好了。跨度>
  • @Anzel 合法并不意味着在这里!我认为这是一种侮辱,当有人在很多人给他答案之后完全编辑他的问题时。
  • @KasraAD,你说得对,我们是来帮忙的,而不是被侮辱。

标签: python list sum product brute-force


【解决方案1】:

这里是:

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])

【讨论】:

  • 数学很好,但既然 OP 谈论的是“非常大”的列表,我猜迭代方法会表现得更好。但是很好......
  • 对于非常大的列表,您可能会受益于 numpy,并使用 (np.sum(xs)**2 - np.sum(x**2)) / 2
【解决方案2】:

使用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 answergeorg's answer 使用更好的算法,并且很容易胜过我对大型列表的回答。

【讨论】:

  • Downvoter,我将不胜感激解释性评论。谢谢!
  • 我想我们所有人都出乎意料地得到了一个-ve,就像 OP 如何改变他的问题一样。老实说,我认为您的回答是向您解释最彻底的 +1。
  • 为突然的变化道歉,我认为这不会造成冲突!
  • 很好,我不知道有combinations 方法,所以我在下面改用permutations
【解决方案3】:

注意:其实@Eastsun's answer更好。

这是另一种更“算法”的处理方式。观察给定的

a0, a1, ..., an

所需的总和是(由于分配律)

a0 (a1 + a2 + ... + an) + a1 (a2 + a3 + ... + an) + ... + an-2 (an-1 + an) + an-1 an

这导致了以下算法:

  • sum 为0,current 为最后一个元素
  • 每一步
    • sumcurrent 相乘并添加到结果中
    • 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

【讨论】:

  • 这是一个非常好的答案,但请考虑不要使用名称sum,因为它隐藏了内置功能。
  • @StevenRumbalski:暂时扮演魔鬼的拥护者,关于这个“不要隐藏内置插件”的问题有点过分炒作。首先,代码应该位于一个小的独立函数中,因此它不会以任何方式影响程序中的其他sums。其次,IMO,python对全局变量的使用是该语言的缺陷之一。 GvR 设法保留所有“酷”的名字供他自己使用!特别是我讨厌我的 IDE 每次都高亮 id(这在任何与 DB 相关的代码中都是必不可少的),而且我一生中从未使用过 python 的 id()
【解决方案4】:

def sumOfProductsOfCouples(l): return sum(l[i-1] * l[i] for i, n in enumerate(l))

【讨论】:

    【解决方案5】:

    在没有外部库的情况下,您可以使用maplambda 成对计算*,然后将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
    

    所以它的作用是取出列表的第一个元素和* 其余部分。重复直到没有任何东西可以从列表中取出。

    【讨论】:

    • 结果不应该是24,应该是35。
    • 这真的很好,但不能满足我的需要,请查看问题,如果我得到一个整数而不是列表,我必须对 range(1 , 整数+1)。我应该使用 list = range(1, Integer + 1) 还是我可以做一些更有效的事情
    • @howaboutNO,OP刚刚改变了问题!环顾四周!
    • @lavee_singh,我根据您的新要求进行了编辑。你可以检查它是否工作。如果给你一个interger,把它放在一个列表中。
    • @lavee_singh,喜欢这个if type(input)==int: input=[input]
    【解决方案6】:
    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.的总和

    【讨论】:

      【解决方案7】:

      使用itertools 模块中的permutations 方法:

      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
      

      【讨论】:

        【解决方案8】:

        您可以使用 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
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2022-07-03
          • 2011-04-20
          • 2021-06-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-08-30
          • 1970-01-01
          相关资源
          最近更新 更多