【问题标题】:How to duplicate elements in a nested list?如何复制嵌套列表中的元素?
【发布时间】:2020-12-10 12:08:11
【问题描述】:

我有一个如下所示的嵌套列表:

[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

我想将每个内部列表中的每个元素复制 3 并将它们并排放置:

[[1, 1, 1, 2, 2, 2, 3, 3, 3], [4, 4, 4, 5, 5, 5, 6, 6, 6], [7, 7, 7, 8, 8, 8, 9, 9, 9]]

这是我目前的解决方案:

from itertools import repeat

x2 = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

ls = []
for i in x2:
    ls.append([x for item in i for x in repeat(item, 3)])
ls
>>> [[1, 1, 1, 2, 2, 2, 3, 3, 3],
 [5, 5, 5, 6, 6, 6, 7, 7, 7],
 [9, 9, 9, 10, 10, 10, 11, 11, 11],
 [4, 4, 4, 8, 8, 8, 3, 3, 3]]

有什么方法可以让它更快?

【问题讨论】:

  • 如果你使用 lambda x 函数,有一种方法可以使用 np.repeat()!首先使用'f = lambda x:np.repeat(x2,3)'。然后使用 'np.apply_along_axis(f,1,x)' 你会得到同样的答案。
  • 如果您的代码没有任何问题并且您正在寻求改进; Code Review 是正确的地方,而不是 Stack Overflow。
  • 哦,抱歉,这是我第一次提交问题,谢谢您的意见,下次我会这样做。
  • 谢谢,似乎也可以:)
  • 这可以通过单行列表理解dupes = [[val for val in sublist for i in range(3)] for sublist in x2] 来完成。不知道它是否更快。

标签: python itertools nested-lists


【解决方案1】:

这是一种解决方案:

ls=[sum([[i]*3 for i in k], []) for k in x2]

>>>print(ls)
[[1, 1, 1, 2, 2, 2, 3, 3, 3], [4, 4, 4, 5, 5, 5, 6, 6, 6], [7, 7, 7, 8, 8, 8, 9, 9, 9]]

【讨论】:

    【解决方案2】:

    正如您所要求的更快,以下是此处与其他地方介绍的不同可能方式之间的一些比较。

    结果(在我的机器上)是(按升序排列):

    using_zip         5.630
    using_repeat_comp 5.818
    using_sum         5.905
    using_repeat      6.421
    using_pure        6.878
    

    (对我来说)令人惊讶的是,zip 解决方案实际上是最快的,而您的repeat 解决方案的 list-comp 版本第二。我会假设“纯”列表组合将是最快的,但实际上是最差的。我猜TIL...


    还有一个结果(@Henry Tjhia提出的):

    using_sort        3.219
    

    如您所见,明显更好,但我将其分开放置,因为它严重依赖于上述具体示例。因此,如果您想复制升序数字列表,那将是您的最佳选择。


    生成它们的代码是:

    import timeit
    from itertools import repeat
    
    x2 = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
    
    def using_repeat():
        ls = []
        for i in x2:
            ls.append([x for item in i for x in repeat(item, 3)])
        return ls
    
    def using_repeat_comp():
        return [[x for item in i for x in repeat(item, 3)] for i in x2]
    
    def using_zip():
        return [[x for triple in zip(l, l, l) for x in triple] for l in x2]
    
    def using_sum():
        return [sum([[i]*3 for i in k], []) for k in x2]
    
    def using_pure():
        return [[val for val in sublist for _ in range(3)] for sublist in x2]
    
    def using_sort():
        return [sorted(sub[:]*3) for sub in x2]
    
    for func in [using_repeat, using_repeat_comp, using_zip, using_sum, using_pure, using_sort]:
        print(func.__name__, timeit.timeit(f"{func.__name__}()", f"from __main__ import {func.__name__}"))
    

    【讨论】:

    • 啊,你打败了我:我刚刚完成我的timeit 对相同方法的测试,+1!。 zip 是最快的,这让我很感兴趣。它也是“最少”可扩展的方法,假设用户突然想要 4 个副本而不是 3 个......
    • @Wololo 同意。这也让我感到惊讶。我的自然选择是你的 list-comp,它实际上也是最慢的!
    • 我的错,我刚刚注意到了。在我对您的代码进行的测试中,sum 方式始终优于 zip 和其他方式。
    • @Tomerikoo 那太好了。但是由于顺序很重要,我们可以忘记它:)。
    • @HenryTjhia,不,别忘了。在优化方面,特定的问题可能往往需要特定的解决方案,这样的性能提升不容小觑。这让我大开眼界,也给我上了宝贵的一课。
    猜你喜欢
    • 2023-03-26
    • 1970-01-01
    • 2021-12-03
    • 1970-01-01
    • 1970-01-01
    • 2019-07-13
    • 1970-01-01
    • 2022-01-23
    • 2021-06-16
    相关资源
    最近更新 更多