将列表列表与python中的某个长度的另一个列表列表相结合

时间:2017-02-07 15:12:20

标签: python

我正在寻找一个转换

的班轮
[[1], [1, 1], [1, 1, 1], [1], [1], [1], [1, 1, 1, 1]]

[[1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1, 1]]

其中算法将列表组合到一定的阈值长度。

我目前有这个

batched = []
batch = []
for l in lists:
    batch.extend(l)
    if len(batch) > threshold:
        batched.append(batch)
        batch = []

5 个答案:

答案 0 :(得分:5)

你的原始实现没有任何问题,但如果你坚持使用oneliner这里有一个丑陋的选择:

from itertools import accumulate, chain, groupby

THRESHOLD = 3
l = [[1], [1, 1], [1, 1, 1], [1], [1], [1], [1, 1, 1, 1]]
res = [[y for x in g for y in x[1]]
       for k, g in groupby(zip(chain([0], accumulate(len(x) for x in l)), l),
                           lambda x: x[0] // THRESHOLD)]
print(res)

输出:

[[1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1, 1]]

我们的想法是生成(item count so far, sublist)元组列表,并将计数除以THRESHOLD进行分组。

>>> temp = list(zip(chain([0], accumulate(len(x) for x in l)), l))
>>> temp
[(0, [1]), (1, [1, 1]), (3, [1, 1, 1]), (6, [1]), (7, [1]), (8, [1]), (9, [1, 1, 1, 1])]
>>> groups = [list(g) for k, g in groupby(temp, lambda x: x[0] // THRESHOLD)]
>>> groups
[[(0, [1]), (1, [1, 1])], [(3, [1, 1, 1])], [(6, [1]), (7, [1]), (8, [1])], [(9, [1, 1, 1, 1])]]
>>> [[y for x in g for y in x[1]] for g in groups]
[[1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1, 1]]

答案 1 :(得分:4)

破解它但只是因为我很顽固。它虽然非常丑陋且效率低下,但也许有一种更清洁的方式,但即使有,它也不值得。

a = [[1], [1, 1], [1, 1, 1], [2], [1], [1], [1, 1, 1, 1]]

b = [[[item for sublist in a for item in sublist][x+(y*3)] for x in range(1,4)] for y in range(0, (len([i for j in a for i in j])/3))]
编辑:因为我在Python 2.7中对此进行了测试,所以我错过了在Python 3中分区工作方式不同的事实。感谢@ nexus66指出了一个修改(这使得它更长!)。

c = [[[item for sublist in a for item in sublist][x+(y*3)] for x in range(1,4)] for y in range(0, int((len([i for j in a for i in j])/3)))]

答案 2 :(得分:3)

这可能不太理想,但这将是我的尝试。我们的想法是将您的列表与itertools.chain链接在一起,然后使用itertools.islice从链中拉出并附加一个新列表,直到您不能再使用它为止。诚然,这不是一个班轮。

from itertools import chain, islice
def grouper(n, li):
    it = chain(*li)
    out_l = []
    while True:
        chunk = list(islice(it, n))
        if len(chunk) < n:
            if chunk:
                out_l[-1] += chunk
            return out_l
        out_l.append(chunk)

<强>演示

In[238]: orig = [[1], [1, 1], [1, 1, 1], [1], [1], [1], [1, 1, 1, 1]]
In[239]: grouper(3, orig)
Out[239]: [[1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1, 1]]
In[240]: grouper(4, orig)
Out[240]: [[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1, 1]]
In[241]: grouper(5, orig)
Out[241]: [[1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1]]
Out[242]: grouper(1, orig)
Out[242]: [[1], [1], [1], [1], [1], [1], [1], [1], [1], [1], [1], [1], [1]]

答案 3 :(得分:0)

这是一个丑陋的单行... 它不是完全你所要求的(非常接近),但也许它&#39; ll给你一些如何处理它的想法...

arr = [[1], [1, 1], [1, 1, 1], [1], [1], [1], [1, 1, 1, 1]]

threshold = 4

[[x for y in arr for x in y][i:i+threshold] 
     for i, _ in enumerate([x for y in arr for x in y])
       if i % threshold == 0]

Out[31]:
[[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [1]]

答案 4 :(得分:0)

我很欣赏所有的帮助,而且我了解到一个班轮对于这个问题不是最好的,因为它很丑陋且难以理解并且可能效率低下。话虽如此,我确实想出了这个,这似乎是采用一种不同的略微清洁的方法。

>>> from functools import reduce
>>> l = [[1], [2, 3], [4, 5, 6], [7], [8], [9], [10, 11, 12, 13]]
>>> t = 3
>>> b = reduce(lambda p, n: p[:-1] + [p[-1] + n] if len(p[-1]) + len(n) <= t or not p[-1] else p + [n], l, [[]])
>>> b
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12, 13]]