0

I have flat lists like this:

A [2, -4, 3, 3, 1, 2, 1, 4, -1] B [1, 2, 3, 4, 5, 6]

and I want to reshape them into

A [[2, -4, 3], [3, 1, 2], [1, 4, -1]]

B [[1, 2], [3, 4], [5, 6]]

Is there a light-weight function to do this without using numpy?

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
  • `I have a list` ... what you posted for your list definition is not valid Python code. – Tim Biegeleisen Sep 30 '22 at 01:42
  • 2
    Why do you still label numpy when you don't want to use it? – Mechanic Pig Sep 30 '22 at 01:42
  • 1
    It seems like you are asking for the opposite of flattening. If you google chunking instead of flattening, you will find a lot of answers. – Mark Sep 30 '22 at 01:43
  • 1
    Welcome to Stack Overflow. Please read [ask]. Please use tags to indicate what the question **is** about, not what it isn't about. If you want to solve a problem *without* Numpy, then don't tag it `numpy`. Anyway, please see the linked duplicate. – Karl Knechtel Sep 30 '22 at 02:57

2 Answers2

2

sure you can use this recipe with iter and zip to group by a size

def group_size(L,size):
    return list(zip(*[iter(L)]*size))

print(group_size([1,2,3,4,5,6,7,8,9],3))
Joran Beasley
  • 110,522
  • 12
  • 160
  • 179
-2

OK, there is an excellent answer by Joran Beasley so let's use it along with a recipe for flattening a list in a function able to reshape both flat and a 2D lists to desired shape:

def reshape_list(L, xsize, ysize=None, fillna=False):
    if isinstance(L[0], list):
        _L = [] 
        for l in L: _L+=l
        L = _L 
    if not fillna: 
        if ysize:
            assert xsize*ysize == len(L)
        else: 
            assert len(L)%xsize == 0
        return list(map(list,zip(*[iter(L)]*xsize)))
    else: 
        gap = []
        if ysize:
            if xsize*ysize > len(L): 
                gap = [None]*(xsize*ysize - len(L))
        else: 
            v, r = divmod(len(L),xsize)
            gap = [None]*r
        return list(map(list, zip(*[iter(L+gap)]*xsize)))

print(reshape_list([1,2,3,4,5,6], 2)) 
print(reshape_list([[1,2],[3,4],[5,6]], 3))

gives:

[[1, 2], [3, 4], [5, 6]]
[[1, 2, 3], [4, 5, 6]]

And as we are reshaping lists it might be also of interest how to transpose a 2D list as transposing a 2D list will deliver another result as reshaping:

def transpose_2D_list(L):
    return list(map(list,zip(*L)))

print(transpose_2D_list([[1,2],[3,4],[5,6]]))

gives:

[[1, 3, 5], [2, 4, 6]]

^-- notice the difference to reshaping with xsize=3

Claudio
  • 7,474
  • 3
  • 18
  • 48