Most Pythonic Way To Extend A List To Exactly A Certain Length?
Solution 1:
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.
defpad_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 literal, but you can use a list comprehension the exact same way 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[:] = <...>
.
Some brief timeit
results indicated that literal multiplication is a bit quicker than the double-iteration implied by a list comprehension.
For posterity, the list comprehension version would look something like:
return some_list[:target_len] + [0for _ in range(target_len - len(some_list))]
Solution 2:
It is quite inefficient to build the list bigger than you need it (particularly if n
gets large); instead, only add the padding you need. Also, it is Python convention to return None
if a function changes its argument(s) in-place:
defsome_func(l, n, pad=0):
iflen(l) >= n:
del l[n:]
else:
l.extend([pad] * (n - len(l)))
Example:
>>>l = [1, 2, 3, 4, 5]>>>some_func(l, 3)>>>l
[1, 2, 3]
>>>some_func(l, 5)>>>l
[1, 2, 3, 0, 0]
Alternatively, return
a new list:
defsome_func(l, n, pad=0):
iflen(l) >= n:
return l[:n]
return l + ([pad] * (n - len(l)))
Solution 3:
How about islice
-ing the concatenation of the original list with a padding generator?
from itertools import islice, repeat
deffit_to_size(l, n):
returnlist(islice(
( x
for itr in (l, repeat(0))
for x in itr ),
n))
You might prefer this slightly more explicit implementation:
deffit_to_size(l, n):
defgen():
yieldfrom l
whileTrue: yield0returnlist(islice(gen(), n))
Solution 4:
Why not use conditional logic?
defpad_or_slice(L, n):
iflen(L) < n:
return L + ([0] * (n - len(L)))
else:
return L[:n]
This way you're only doing one of the two, not both, at the cost of checking the length of the list, which shouldn't be too costly.
Solution 5:
It's not significantly more efficient, but I'd do l = (l + [0] * (n - len(l)))[:n]
. So your some_function
would look like this
defsome_function(list, n):
return (list + [0] * (n - len(list)))[:n]
Post a Comment for "Most Pythonic Way To Extend A List To Exactly A Certain Length?"