1

I have a list of lists that look something like this:

[
  [12, 4, 6],
  [55],
  [102, 7, 7, 2]
]

What would be the best way to prefix them with 0-elements to make them the same size. Expected outcome:

[
  [0, 12, 4, 6],
  [0, 0, 0, 55],
  [102, 7, 7, 2]
]
Daniel
  • 20,420
  • 10
  • 92
  • 149

5 Answers5

7

you can use:

m = max(map(len, l))
l = [[0] * (m - len(i)) + i for i in l ]
l

# [[0, 12, 4, 6], [0, 0, 0, 55], [102, 7, 7, 2]]
kederrac
  • 16,819
  • 6
  • 32
  • 55
2

you can so something like that:

a = [ 
  [12, 4, 6], 
  [55], 
  [102, 7, 7, 2] 
]   

my_max = max((map(len, a)))  


for i in a: 
   while len(i) < my_max : 
       i.insert(0, 0) 

a                                             
[[0, 12, 4, 6], [0, 0, 0, 55], [102, 7, 7, 2]]



Beny Gj
  • 607
  • 4
  • 16
2

Here are some performance characteristics for proposed solution as well as a solution using itertools.

TLDR; Solution proposed by @kederrac is 2 times faster compared to a solution with itertools. The solution proposed by @Beny is 60 times slower.

If the new list is list of iterators instead of lists, the solution using itertools is 6 times faster compared to solution from @Kederrac

Here are the actual numbers -

mahorir@mahorir-Vostro-3446:~/Desktop$ python3 --version
Python 3.6.9

For Large lists, for 10000 iterations -

mahorir@mahorir-Vostro-3446:~/Desktop$ python3 so-28.py 
with_iter : 1.070244312286377
with_iter_retrun_iter : 0.09145450592041016
without_iter : 0.6605610847473145
with_insert : 60.93585515022278

For small lists (10000) iterations -

mahorir@mahorir-Vostro-3446:~/Desktop$ python3 so-28.py 
with_iter : 0.040375709533691406
with_iter_retrun_iter : 0.026880741119384766
without_iter : 0.01978278160095215
with_insert : 0.034635305404663086

Code -

import itertools as it
from timeit import time

def with_iter():
    l=[
    [12, 4, 6]*1000,
    [55],
    [102, 7, 7, 2]
    ]
    m = max(map(len, l))
    n = [list(it.chain(it.repeat(0,m-len(i)),i)) for i in l]

def with_iter_retrun_iter():
    l=[
    [12, 4, 6]*1000,
    [55],
    [102, 7, 7, 2]
    ]
    m = max(map(len, l))
    n = [(it.chain(it.repeat(0,m-len(i)),i)) for i in l]


def without_iter():
    l=[
    [12, 4, 6]*1000,
    [55],
    [102, 7, 7, 2]
    ]

    m = max(map(len, l))
    n = [[0] * (m - len(i)) + i for i in l ]

def with_insert():
    a = [ 
    [12, 4, 6]*1000, 
    [55], 
    [102, 7, 7, 2] 
    ]
    my_max = max((map(len, a)))
    for i in a: 
        while len(i) < my_max : 
            i.insert(0, 0) 

if __name__ == "__main__":
    a=time.time()
    for i in range(10000):
        with_iter()
    print("with_iter", time.time()-a, sep=" : ")

    a=time.time()
    for i in range(10000):
        with_iter_retrun_iter()
    print("with_iter_retrun_iter", time.time()-a, sep=" : ")

    a=time.time()
    for i in range(10000):
        without_iter()
    print("without_iter", time.time()-a, sep=" : ")

    a=time.time()
    for i in range(10000):
        with_insert()
    print("with_insert", time.time()-a, sep=" : ")


Code is same as above, just the lists inside each method is this as OPs list

l=[
    [12, 4, 6],
    [55],
    [102, 7, 7, 2]
    ]

mahoriR
  • 4,377
  • 3
  • 18
  • 27
0

The following function will do it for you. Not sure how elegant it is.

def padded_list(my_list):
    max_elems = max([len(i) for i in my_list])
    new_list = [[0]*(max_elems - len(i)) + i for i in my_list]
    return new_list
Morne
  • 11
  • 3
0

You can do this,

maxLen = max(map(len, arr))
[row.extend(['0']*(maxLen - len(row))) for row in arr]

#[[12, 4, 6, '0'], [55, '0', '0', '0'], [102, 7, 7, 2]]
Avishka Dambawinna
  • 1,180
  • 1
  • 13
  • 29