Home > Enterprise >  How to separate a 1D list into a 2D list with 1D lists of decreasing length, down to 1
How to separate a 1D list into a 2D list with 1D lists of decreasing length, down to 1

Time:10-09

If I had the 1D list:

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

How would I separate the 1D list so that it would make a 2D list that has 1D elements of decreasing length, down to 1?

For example, the above list would become:

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

I am aware this only works with lists of certain lengths, but in this case I only need it to work for those ideal lengths.

CodePudding user response:

if no other solution is coming to your mind ,just start forming new lists from the end, it will be an O(n) solution.

CodePudding user response:

With a generator

Let's make a generator which will return the elements of a list as if they were in a flattened triangular matrix:

def tril(arr):
    '''Iterate over the list as a lower triangular matrix,
    e.g. if arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] then return one by one:
    [1]
    [2, 3]
    [4, 5, 6]
    [7, 8, 9, 10]
    '''
    N = len(arr)
    left, width = 0, 1
    while left < N:
        yield arr[left:(right:=left width)]
        left = right
        width  = 1

With [i for i in tril([*range(1,11)]) we get a list:

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

So to get the required answer we have to apply reversing three times - to a given list arr = [*range(1,11)], to each item from tril(reversed(arr)), and to the whole output list:

arr = [*range(1, 11)]
answer = [i[::-1] for i in tril(arr[::-1])][::-1]

Knowing the lenght of the first item

We can calculate the length of the first item from the equation:

n*(n 1) == 2*len(arr)

where arr is a given list if items, and n is the lenght of the first item of the required answer, e.g if arr = [*range(1, 11)] then n == 4. In other words, len(arr) is equal to the sum of first n natural numbers.

So we can obtain the answer this way:

arr = [*range(1, 11)]
n = round(((8*len(arr)   1)**0.5 - 1)/2)

# Usually we know the value of n
# so only the next 2 lines is needed in common case
item = iter(arr)
answer = [[next(item) for _ in range(i)] for i in range(n, 0, -1)]
  • Related