Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Most pythonic way to extend a list to exactly a certain length? [duplicate]

Tags:

python

My goal is to take a list of unknown number of elements and extend/slice it to exactly n elements, padding lists that are too short with 0 and slicing lists that are too long.

For example

n = 10
foo = [1,2,3,4]
print some_func(foo,n) 

should return [1,2,3,4,0,0,0,0,0,0], and

n = 10
foo = [1,2,3,4,5,6,7,8,9,10,11,12]
print some_func(foo,n)

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


Right now I'm doing this:

def some_function(l, n):
    l.extend([0] * n)
    l = l[:n]
    return l

But that seems inefficient. Is there a more pythonic way of doing this?


EDIT: point of clarification, I am not trying to modify the original array, I am returning a new array that can be a shallow copy.

like image 488
Hans Z Avatar asked Jun 05 '14 17:06

Hans Z


People also ask

What is extend () method in list?

The extend() method adds the specified list elements (or any iterable) to the end of the current list.

How do you repeat elements in a list?

To repeat elements of a list using the extend() method, we will copy the elements of the existing list in a temporary list. After that, we will use the extend() method with a for loop to repeat the elements of the list as follows.


1 Answers

The only potentially "more Pythonic" way to do this is pretty much the way you have it, but skip over the extra variable allocation and just return the result directly. You could also definitely make it more Pythonic by conforming to PEP8 with your function and variable names.

Besides that, you can improve your efficiency by adding only as many zeroes as you need, rather than building a too-long list and then trimming it.

def pad_or_truncate(some_list, target_len):
    return some_list[:target_len] + [0]*(target_len - len(some_list))

Breaking it down, there are two cases represented here (discounting the trivial case where the input is exactly the right length already). Either the list is too long, or the list is too short.

If the list is too long, we just slice it. some_list[:target_len] takes care of that. Because the slice operation is friendly, this won't blow up if the target length is beyond the actual length of the list.

If the list is too short, we pad it with zeroes. I chose to do this by multiplying a list literal1, but you can use a list comprehension the exact same way2 if that's more your cup of tea. Just determine how many zeroes to add (either zero, if the list isn't too short, or target_len - len(some_list)), and concatenate a list composed of that many zeroes. Done and done!

If you want to make it an in-place operation (as your original example appears to be trying but failing to achieve; see @chepner's comment), you would just change return <...> to some_list[:] = <...>.


1Some brief timeit results indicated that literal multiplication is a bit quicker than the double-iteration implied by a list comprehension.

2For posterity, the list comprehension version would look something like:

return some_list[:target_len] + [0 for _ in range(target_len - len(some_list))]
like image 90
Henry Keiter Avatar answered Oct 17 '22 07:10

Henry Keiter