Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Combine list of lists to another list of lists by a certain length in python

Tags:

python

I'm looking for a one liner to convert

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

to

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

where the algorithm combines the lists up to a certain threshold length.

I currently have this

batched = []
batch = []
for l in lists:
    batch.extend(l)
    if len(batch) > threshold:
        batched.append(batch)
        batch = []
like image 604
shane Avatar asked Feb 04 '26 00:02

shane


2 Answers

There's nothing wrong with your original implementation but if you insist oneliner here's one ugly option:

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)

Output:

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

The idea is to generate list of (item count so far, sublist) tuples and group them by dividing count by 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]]
like image 145
niemmi Avatar answered Feb 05 '26 14:02

niemmi


Cracked it but only because I'm stubborn. It's really ugly and inefficient though and maybe there's a cleaner way but, even if there is, it's not worth it.

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))]

EDIT: Because I was testing this in Python 2.7 I missed the fact that division works differently in Python 3. Thanks @nexus66 for pointing out a modification (which just makes it even longer!).

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)))]
like image 29
roganjosh Avatar answered Feb 05 '26 13:02

roganjosh