【问题标题】:Python: adding elements in nested list if the first two elements are the samePython:如果前两个元素相同,则在嵌套列表中添加元素
【发布时间】:2016-04-29 21:41:45
【问题描述】:

我有一个嵌套列表:

 a = [[1,2,3,4,5],[1,2,5,6,7],[1,2,5,2,1],[1,3,4,5,7],[3,4,1,2,3],[3,4,1,1,1]]

如果子列表的前两个元素相同,那么我想添加它们对应的第 3、第 4 和第 5 个元素,同时保留前两个元素。对于上述情况,结果应该是:

a = [[1,2,13,12,13],[1,3,4,5,7],[3,4,2,3,4]]

有没有办法做到这一点?

谢谢。

【问题讨论】:

  • 这些结构是列表。你试过什么?

标签: python list nested


【解决方案1】:

您可以使用字典根据前两个项目对子列表进行分类,然后遍历这些项目并计算总和:

>>> d = {}
>>> for sub in a:
...    d.setdefault(tuple(sub[:2]),[]).append(sub[2:])
... 

>>> 
>>> [k+tuple(map(sum, zip(*v))) for k,v in d.items()]
[(1, 2, 13, 12, 13), (1, 3, 4, 5, 7), (3, 4, 2, 3, 4)]

【讨论】:

    【解决方案2】:

    熊猫单线

    pandas 单线怎么样。

    导入和数据:

    >>> import pandas as pd
    >>> a = [[1,2,3,4,5],[1,2,5,6,7],[1,2,5,2,1],[1,3,4,5,7],[3,4,1,2,3],[3,4,1,1,1]]
    

    熊猫在行动:

    >>> pd.DataFrame(a).groupby([0, 1]).sum().reset_index().values.tolist()
    [[1, 2, 13, 12, 13], [1, 3, 4, 5, 7], [3, 4, 2, 3, 4]]
    

    一步一步

    制作数据框:

    >>> df = pd.DataFrame(a)
    
       0  1  2  3  4
    0  1  2  3  4  5
    1  1  2  5  6  7
    2  1  2  5  2  1
    3  1  3  4  5  7
    4  3  4  1  2  3
    5  3  4  1  1  1
    

    按前两列分组并对其他列求和:

    >>> df2 = df.groupby([0, 1]).sum()
    >>> df2
    
          2   3   4
    0 1            
    1 2  13  12  13
      3   4   5   7
    3 4   2   3   4
    

    groupby 方法按列01 分组。结果是一个GroupBy 对象。你需要用它“做”一些事情来可视化它。在这里,我们对组中的值求和。或许看看格式精美的表格会更清楚一些:

    这个索引是MultiIndex:

    MultiIndex(levels=[[1, 3], [2, 3, 4]],
               labels=[[0, 0, 1], [0, 1, 2]],
               names=[0, 1])
    

    有两个级别,名称为01。最左边的列是带有标签13 的第一层,接下来是带有标签234 的第二层。第一级中的标签1 用于前两行。所有其他标签仅用于一行。

    扁平化多索引:

    >> df3 = df2.reset_index()
    
       0  1   2   3   4
    0  1  2  13  12  13
    1  1  3   4   5   7
    2  3  4   2   3   4
    

    转换成列表:

    >>> df3.values.tolist()
    [[1, 2, 13, 12, 13], [1, 3, 4, 5, 7], [3, 4, 2, 3, 4]]
    

    【讨论】:

    • 哇!我对熊猫一无所知。谢谢!
    • @mike:如果你能添加更多关于“groupby”如何工作的解释,那就太好了。我明白了,但仍不清楚。
    • @kmario23 添加了更多解释。
    • 我不知道为什么我得到 [[1L, 2L, 13L, 12L, 13L], [1L, 3L, 4L, 5L, 7L], [3L, 4L, 2L, 3L, 4L]] 代替!
    • 您正在使用 Python 2,并且您可能在 Windows 上。在 Windows 上,即使在 64 位系统上,标准整数也是 32 位的。但数据帧使用 64 位整数。这些被转换成 Python long(整数)。它们的字符串表示以L 为后缀。尝试使用 Python 3,您将看不到 L。如果您不喜欢 long 转换为 int32:import numpy as np; df3.values.astype(np.int32).tolist()
    【解决方案3】:

    我会创建一个字典,其中第一对作为键,值是列表或元组:

    a=[[1,2,3,4,5],[1,2,5,6,7],[1,2,5,2,1],[1,3,4,5,7],[3,4,1,2,3],[3,4,1,1,1]]
    
    #create empty dict
    d = {}
    
    # function for adding list b to lists a
    def addlist(a,b): return [a[i]+b[i] for i in range(len(a))]  
    
    # now iter through each item and add to existing or create a new record in dictionary
    for i in a:
        d[tuple(i[:2])] = addlist(d.setdefault(tuple(i[:2]),[0,0,0]),i[2:])
    
    #the wanted output would be
    [list(k)+v for k,v in d.items()]
    

    【讨论】:

      【解决方案4】:

      这是itertools.groupby 的一个相对简单的应用程序。

      下面是使用嵌套列表推导的方法。

      from itertools import groupby
      from operator import itemgetter
      
      a = [[1,2,3,4,5],[1,2,5,6,7],[1,2,5,2,1],[1,3,4,5,7],[3,4,1,2,3],[3,4,1,1,1]]
      expected = [[1,2,13,12,13],[1,3,4,5,7],[3,4,2,3,4]]
      print(expected)
      
      a = [list(k) + [sum(t) for t in zip(*[u[2:] for u in g])]
          for k, g in groupby(a, itemgetter(0, 1))]
      print(a)
      

      输出

      [[1, 2, 13, 12, 13], [1, 3, 4, 5, 7], [3, 4, 2, 3, 4]]
      [[1, 2, 13, 12, 13], [1, 3, 4, 5, 7], [3, 4, 2, 3, 4]]
      

      请注意,这假定列表 a 已经具有以相邻的相同 2 个元素开头的子列表。如果不是这种情况,则应对其进行排序,例如

      a.sort(key=itemgetter(0, 1))
      

      在运行上述代码之前。

      为了便于阅读和分析,这里将基本相同的算法分开。

      keyfunc = lambda seq: seq[:2]
      
      a.sort(key=keyfunc)
      new_a = []
      for k, g in groupby(a, key=keyfunc):
          tails = [u[2:] for u in g]
          sums = [sum(t) for t in zip(*tails)]
          new_a.append(k + sums)
      
      print(new_a)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-02-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多