在Python中按长度拆分列表列表

时间:2013-11-27 22:52:03

标签: python list

考虑到以下问题,在Python中执行此操作的最有效(或合理有效)方法是什么:

问题。鉴于列表清单,

L = [list_0, list_1, list_2, list_3, ..., list_n]

其中len(list_i)< = 3,假设L内的每个列表。我们如何将L分成L_1,L_2,L_3,其中L_1只有长度为1的列表,L_2只有长度为2的列表,L_3只有3个长度列表?

潜在的解决方案。这是我能做的最好的事情;我也在这里也包括了一个样本集。它在我的电脑上运行大约8.6秒。

import time

# These 4 lines make a large sample list-of-list to test on.
asc_sample0 = [[i] for i in range(500)]
asc_sample1 = [[i,j] for i in range(500) for j in range(20)]
asc_sample2 = [[i,j,k] for i in range(20) for j in range(10) for k in range(20)]
asc_sample = asc_sample0 + asc_sample1 + asc_sample2

start = time.clock()
cells0 = [i for i in asc if len(i) == 1]
cells1 = [i for i in asc if len(i) == 2]
cells2 = [i for i in asc if len(i) == 3]
print time.clock() - start

我还尝试关闭“弹出”元素并附加到列表cell0等,但这花费的时间要长得多。我还试图追加然后删除那个元素,这样我就可以在一个循环中完成,当有10 ^ 10个大小为1的列表,但只有少数大小为2和3时,但是,通常,效率不高。

我非常欣赏一些巧妙的想法。我知道其中一个答案很可能是“用C语言编写”,但是现在我只想看看Python解决方案。

4 个答案:

答案 0 :(得分:2)

旧式解决方案在这里可能会更好用:

cells0, cells1, cells2 = [], [], []

for lst in asc_sample:
    n = len(lst)
    if n == 1:
        cells0.append(lst)
    elif n == 2:
        cells1.append(lst)
    else:
        cells2.append(lst)

答案 1 :(得分:1)

这绝对是最好的之一,因为它并行运行。您应该看到的另一件事是itertools.groupby和内置filter方法。

答案 2 :(得分:1)

result = dict()

for lst in L:
    result.setdefault(len(lst), []).append(lst)

print result

<强>输出

{
 1: [[0], [1], [2], [3]],
 2: [[0, 0], [0, 1], [0, 2]],
 3: [[0, 0, 0], [0, 0, 1], [0, 0, 2]]
}

答案 3 :(得分:1)

索引列表/元组应该比执行密钥查找更快。这比问题中给出的版本快约30%

cells = [],[],[],[]     # first list here isn't used, but it's handy for the second version
for i in asc:
    cells[len(i)].append(i)

通过提取附加方法再次快一点(在较大的列表中,这几乎是OP的两倍)

cells = [],[],[],[]
appends = [x.append for x in cells]
for i in asc:
    appends[len(i)](i)