首页 > 解决方案 > 展开具有相同元素的列表

问题描述

假设我有以下嵌套列表:

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

我想把它变成以下:

desired_list = [[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]]

如果我不关心订单,我可以做类似的事情

new_list = [sorted(x*3) for x in initial_list]

但是,顺序应与initial_list. 我能做的最好的是将每个元素放在一个列表中并将其乘以 3(任意数),然后加入结果inner_list

multiplied_list = [[[element]*3 for element in inner_list] for inner_list in initial_list]
desired_list = [[element for element_list in inner_list for element in element_list] for inner_list in multiplied_list]

(在人类理解的两个列表中)

是否有更易于理解/充分/pythonic 的方式来执行此操作?

标签: pythonlistsortinglist-comprehensionnested-lists

解决方案


您可以只使用以下列表理解。请注意,我initial_list与 OP 中的不同,以证明保留了订单。

代码:

>>> initial_list = [[1, 3, 2], [4, 5, 6], [7, 8, 9]]
>>> [[x for x in sl for _ in range(3)] for sl in initial_list]
[[1, 1, 1, 3, 3, 3, 2, 2, 2],
 [4, 4, 4, 5, 5, 5, 6, 6, 6],
 [7, 7, 7, 8, 8, 8, 9, 9, 9]]

或者,在您的示例中向 sorted 函数添加一个键:

>>> [sorted(x*3, key=x.index) for x in initial_list]
[[1, 1, 1, 3, 3, 3, 2, 2, 2],
 [4, 4, 4, 5, 5, 5, 6, 6, 6],
 [7, 7, 7, 8, 8, 8, 9, 9, 9]]

具有不同 n*n 列表大小的方法的时间比较:

在此处输入图像描述

使用perfplot生成- 代码重现:

from itertools import chain
from functools import reduce
import perfplot
from copy import deepcopy
import numpy as np
import random

def shuffle(x):
    random.shuffle(x)
    return x

def cdjb(initial_list):
    return [[x for x in sl for _ in range(3)] for sl in initial_list]

def aurora_sorted(initial_list):
    return [sorted(x*3, key=x.index) for x in initial_list]

def aurora_list_comp(initial_list):
    return [[element for element_list in inner_list for element in element_list] for inner_list in [[[element]*3 for element in inner_list] for inner_list in initial_list]]

def kederrac(initial_list):
    new_list = deepcopy(initial_list)
    for l in new_list:
        for j in range(0, 3*len(l), 3):
            l[j: j + 1] = [l[j]] * 3
    return new_list

def alain_chain(initial_list):
    return [list(chain(*(i3 for i3 in zip(*[sl]*3)))) for sl in initial_list]

def alain_reduce(initial_list):
    return [list(reduce(lambda a,e:a+[e]*3,sl,[]))for sl in initial_list]

def alain_zip(initial_list):
    return [[i for i3 in zip(*[sl]*3) for i in i3] for sl in initial_list]

def binyamin_numpy(initial_list):
    return np.array(initial_list).repeat(3).reshape(len(initial_list), -1).tolist()


perfplot.show(
    setup=lambda n: [shuffle([i for i in range(n)]) for j in range(n)],
    n_range=[2**k for k in range(12)],
    kernels=[
        cdjb,aurora_sorted, aurora_list_comp, kederrac, alain_chain, alain_reduce, alain_zip, binyamin_numpy
        ],
    xlabel='len(x)',
    )

推荐阅读