Reputation: 1019
I am fairly new to python and am using a list comprehension in the following snippet:
while offset < len(list)
s = ['{:04x}'.format(i) for i in list[offset:offset+16]]
do stuff with s
offset += 16
The snippet loops through the list
and adds up to 16 elements to s in a formatted manner, then adds 16 to the offset value to obtain the next 16 until all elements are seen. This works in my unsimplified code, but I'd like to impose a placeholder for when the slice exceeds the list size, instead of having it just stop adding elements to s
. I know I can do this with a full for loop but would like to try and do this in comprehension for the sake of keeping this concise to one line. I imagine I would need an if/else
in the comprehension but cannot seem to figure out what conditions are needed.
Upvotes: 0
Views: 248
Reputation: 152725
The easiest way would be to use some sort of grouper
that gives you the blocks. The itertools
-module presents such a function:
from itertools import zip_longest # or izip_longest in Python2
def grouper(iterable, n, fillvalue=None):
"Collect data into fixed-length chunks or blocks"
# grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx"
args = [iter(iterable)] * n
return zip_longest(*args, fillvalue=fillvalue)
And with that function you can do it like this:
lst = list(range(20))
for group in grouper(lst, n=8, fillvalue=0):
print(['{:04x}'.format(i) for i in group])
yielding this output:
['0000', '0001', '0002', '0003', '0004', '0005', '0006', '0007']
['0008', '0009', '000a', '000b', '000c', '000d', '000e', '000f']
['0010', '0011', '0012', '0013', '0000', '0000', '0000', '0000']
Upvotes: 0
Reputation: 110486
Concatenate your slice with a list containing placeholders - thus when the slice is over, the placeholders will be fetched, and add to the loop a secondary iterator with the final size you want (a range
will do), to limit the yielded items from the first part:
s = ['{:04x}'.format(i) for i, j in in zip(list[offset:offset+16] + ([placeholder] * 16) , range(16) ) ]
Upvotes: 0
Reputation: 23780
You can dynamically pad the sliced chunk to a fixed size. For example:
while offset < len(l):
s = ['{:04x}'.format(i) for i in l[offset:offset + 16] + [0] * max(0, offset + 16 - len(l))]
offset += 16
# Do something
For example with fixed size of 4, this code:
WIDTH = 4
offset = 0
l = list(range(10))
while offset < len(l):
s = ['{:04x}'.format(i) for i in
l[offset:offset + WIDTH] + [0] * max(0, offset + WIDTH - len(l))]
offset += WIDTH
print(s)
Yields:
['0000', '0001', '0002', '0003']
['0004', '0005', '0006', '0007']
['0008', '0009', '0000', '0000']
Upvotes: 1