【问题标题】:Multiply tuple elements if the first element in a tuple matches else ignore如果元组中的第一个元素匹配,则将元组元素相乘,否则忽略
【发布时间】:2013-05-30 00:22:25
【问题描述】:

我有一个如下所示的元组列表

[(0, 33), (3, 26), (4, 95), (0, 28), (1, 12), (2, 3), (4, 69)]

如果第一个元素匹配(一次或多次),我想将元组的第二个元素相乘;如果不是我忽略元组。所以,输出应该是

33 * 28 + 95 * 69 = 7479

目前,我正在做以下事情:

  1. 使用计数器检查元组的第一个元素是否存在。
  2. 遍历集合以查看是否存在单元素元组或更多;忽略 1 元素的
  3. 迭代地将非 1 元素元组添加到字典并更新乘法
  4. 在字典的values 上使用sum 函数

我想知道是否有一种 Pythonic 方法可以减少这种情况。我很确定我在这里把事情复杂化了。

【问题讨论】:

  • Pythonic 的方式可能是这样的:有一个其键是第一个元素的字典,并且只遍历整个列表一次,更新字典。每个值都包含诸如“是否见过不止一个”和“这是迄今为止这些项目的产品”等信息。
  • 我想知道ifilter之类的东西是否可以提供帮助。
  • 在你的位置上,我会按照我上面描述的一步一步编写算法,而不用担心一些 itertools 函数。

标签: python python-2.7 tuples multiplication


【解决方案1】:

我会编写这样的程序

collection = [(0, 33), (3, 26), (4, 95), (0, 28), (1, 12), (2, 3), (4, 69)]
output = 0
for elem in collection:
    collection.remove(elem)
    new_collection = collection
    part_output = 0
    for new_elem in new_collection:
        if elem[0] == new_elem[0]:
            part_output = (part_output * new_elem[1]) if part_output != 0 else (elem[1] * new_elem[1])
            collection.remove(new_elem)
    output = output + part_output

print output

元组列表只迭代一次,元素被删除,因为不需要。

【讨论】:

    【解决方案2】:

    一旦我按键拆分了您的元组,我将使用reducemul 来获取列表的乘积:

    test = [(0, 33), (3, 26), (4, 95), (0, 28), (1, 12), (2, 3), (4, 69)]
    grouped_by_key = {pair[0] : [] for pair in test} #Initialize dict to hold items
    tmp = [grouped_by_key[pair[0]].append(pair[1]) for pair in test] #Add items in lists by keys
    

    现在导入一些东西:

    from functools import reduce #reduces iterables
    from operator import mul #helps doing multiply for a list
    

    现在使用导入的函数来获得想要的结果:

    sum([reduce(mul,v,1) for v in grouped_by_key.values() if len(v) > 1])
    7479
    

    【讨论】:

      【解决方案3】:

      我会在组合中添加defaultdict 以简化匹配组合。我还包含了生成方程式本身的代码,可以注释掉:

      from collections import defaultdict
      from operator import mul
      
      pairs = [(0, 33), (3, 26), (4, 95), (0, 28), (1, 12), (2, 3), (4, 69)]
      
      table = defaultdict(list)
      
      for key, value in pairs:
          table[key].append(value)
      
      result = 0
      equation = []
      
      for value in table.values():
          if len(value) > 1:
              equation.append(' * '.join(map(str, value)))
              result += reduce(mul, value)
      
      print ' + '.join(equation), '=', result
      

      输出

      33 * 28 + 95 * 69 = 7479
      

      【讨论】:

        【解决方案4】:

        很惊讶这个问题没有好的答案... 这是我的看法:

        test = [(0, 33), (3, 26), (4, 95), (0, 28), (1, 12), (2, 3), (4, 69)]
        unique_keys = set([pair[0] for pair in test]) #{0, 1, 2, 3, 4}
        grouped_by_key = [[el[1] for el in test if el[0] == key] for key in unique_keys] # [[33, 28], [12], [3], [26], [95, 69]]
        grouped_by_key = filter(lambda x: len(x) > 1,grouped_by_key) # [[33, 28], [95, 69]]
        
        add = lambda x, y : x+y
        mul = lambda x, y : x*y
        # Alternatively:
        # from operator import add, mul
        
        out = reduce(add, map(lambda x: reduce(mul, x), grouped_by_key))  #7479
        

        【讨论】:

        • 这不会运行。除了缺少注释字符,xx 是未定义的。此外,共识似乎是答案是 7479,而不是 7476
        • 修复了重命名变量后出现拼写错误的 xx 位。我得到的结果也是正确的......只是从控制台错误地手动粘贴!感谢您发现
        • 在第二行中,您使用三个概念 set maplambda 来获取唯一键,为什么不用 set([pair[0] for pair in test]) 代替呢?列表理解和字典理解非常方便。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-08-18
        • 2017-05-14
        • 1970-01-01
        • 1970-01-01
        • 2015-05-03
        相关资源
        最近更新 更多