As others have said, modifying a list in place when passed to a function is generally not a good idea. But since that's what you're looking for:
- Start at index 1 (2nd element) since the first one with chunk size 1 doesn't need to be flipped.
- Chunk size starts at 2 elements and then increments by 1 for each loop
- Each cunk-sized-slice of the list is assigned that slice in reverse using
-1
for the step and flipping the start and end indexes (+/- 1)
- or use the same index but add a
[::-1]
to reverse it
- The starting index of the next chunk is the current start + current chunksize
- Repeat until
start
reaches end of the list*
l = [1, 2, 3, 4, 5, 6, 7]
def flip(lst):
start = 1
size = 2 # after the first element, next chunk is size 2
while start < len(lst):
lst[start : start + size] = lst[start + size - 1 : start - 1 : -1]
# or, more readable:
# lst[start : start + size] = lst[start : start + size][::-1]
start += size
size += 1
print(l)
flip(l)
print(l)
Output:
[1, 2, 3, 4, 5, 6, 7]
[1, 3, 2, 6, 5, 4, 7]
If after the last chunk, your list has 2 or more elements left, then it will also flip the last chunk, even if the chunk size is less than what the next one should be. For example:
l = [1, 2, 3, 4, 5, 6, 7, 8, 9]
flip(l)
print(l)
# [1, 3, 2, 6, 5, 4, 9, 8, 7] (last 2 chunks are both size 3)
* If the last chunk which is less than the required chunk size should not be flipped, change the loop condition to while start + size <= len(lst):
, which would give:
l = [1, 2, 3, 4, 5, 6, 7, 8, 9]
flip(l)
print(l)
# [1, 3, 2, 6, 5, 4, 7, 8, 9] (7 8 9 is not flipped)
# and works normally when the next chunk is the right size:
l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
flip(l)
print(l)
# [1, 3, 2, 6, 5, 4, 10, 9, 8, 7] (7 8 9 10 is size 4 which is the correct next chunk size)
Edit: And to make it a generator, on the line which does the flipping, instead of assigning it back to the list, put a yield from
.