【问题标题】:Using zip_longest to sum different length lists and fill different lengths from start rather than end使用 zip_longest 对不同长度的列表求和,并从开始而不是结束填充不同的长度
【发布时间】:2019-01-14 15:38:11
【问题描述】:

我有两个列表 [1,2,3,4][1,2,3]

我想总结这些给我以下信息:[1,3,5,7]

这是通过 1+0=12+1=33+2=54+3=7 完成的。

我知道itertools.zip_longest 会这样做,但它会在最后用0 填充长度不匹配,给我[2,3,6,4] 而不是我想要的值。

我希望通过用零填充第一个长度来解决长度不匹配问题。

【问题讨论】:

    标签: python itertools


    【解决方案1】:

    内置的reversed() 函数可以用来做这样的事情:

    from itertools import zip_longest    
    
    def sum_lists(*iterables):
        iterables = (reversed(it) for it in iterables)
        return list(reversed([a+b for a, b in zip_longest(*iterables, fillvalue=0)]))
    
    
    if __name__ == '__main__':
        result = sum_lists([1, 2, 3, 4], [1, 2, 3])
        print(result)  # -> [1, 3, 5, 7]
        result = sum_lists([1, 2, 3], [1, 2, 3, 4])
        print(result)  # -> [1, 3, 5, 7]    # Order of args doesn't matter.
    

    【讨论】:

      【解决方案2】:

      您可以用零填充第二个列表并使用zip

      s1, s2 = [1,2,3,4], [1, 2, 3]
      new_result = [a+b for a, b in zip(s1, ([0]*(len(s1)-len(s2)))+s2)]
      

      输出:

      [1, 3, 5, 7]
      

      【讨论】:

      • 这是假设 s2 总是较短的列表,zip_longest 将确定哪个较短。不错的解决方案,但可能需要上一步来确定要在前面填充哪个列表。
      【解决方案3】:

      您可以使用repeat 构建一个班次,然后使用chain 将班次与较短的班次连接起来:

      from itertools import repeat, chain
      
      first = [1, 2, 3, 4]
      second = [1, 2, 3]
      
      shift = repeat(0, abs(len(first) - len(second)))
      
      result = [a + b for a, b in zip(first, chain(shift, second))]
      
      print(result)
      

      输出

      [1, 3, 5, 7]
      

      【讨论】:

        【解决方案4】:

        您可以使用reversed 函数以相反的顺序生成两个列表,以便zip_longest 将从另一端对齐压缩,然后将结果反转:

        from itertools import zip_longest
        lists = [1,2,3,4], [1, 2, 3]
        print(list(map(sum, zip_longest(*map(reversed, lists), fillvalue=0)))[::-1])
        

        这个输出:

        [1, 3, 5, 7]
        

        【讨论】:

        • 和我的差别不大吧?
        • 我在发布我的之后看到了你的。它们的想法确实相同,但由于我的更通用,因为它可以容纳多个列表,所以我决定把我的留在这里。
        【解决方案5】:

        您可以通过在ziping 与zip_longest 之前反转您的列表来解决此问题。

        from itertools import zip_longest
        
        s1, s2 = [1,2,3,4], [1, 2, 3]
        res = [a+b for a, b in zip_longest(reversed(s1), reversed(s2), fillvalue=0)]
        

        最后,再次逆向,得到想要的结果:

        res = res[::-1]
        print(res)  # [1, 3, 5, 7]
        

        正如@CoryKramer 在他的评论中所说,这种方法的主要优点是您不必事先知道哪个列表最长。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-04-21
          • 2018-05-04
          • 1970-01-01
          • 2022-08-15
          • 1970-01-01
          • 2017-12-04
          • 2013-05-09
          相关资源
          最近更新 更多