Skip to content

Instantly share code, notes, and snippets.

@skywodd
Last active May 4, 2017 14:59
Show Gist options
  • Save skywodd/1d61509b7741d13c53d92763d91eaeb2 to your computer and use it in GitHub Desktop.
Save skywodd/1d61509b7741d13c53d92763d91eaeb2 to your computer and use it in GitHub Desktop.
Slice a page range to create a nice pagination effect.
def slice_pagination_range(page_range, page_number, slice_range):
"""
Slice the given ``page_range`` to +/- ``slice_range`` values around the given ``page_number``.
Center the slice on the given ``page_number`` (one based).
First and last values are always in the output slice.
If required, ellipsis are added as ``None`` values.
"""
nb_pages = len(page_range)
# Avoid slicing on small range
if nb_pages <= slice_range * 2 + 3:
yield from page_range
return
# Get slice start and stop indexes
page_number -= 1 # zero based index
last_index = nb_pages - 1
slice_start = max(1, page_number - slice_range)
slice_stop = min(last_index - 1, page_number + slice_range)
# Left ellipsis
yield page_range[0]
if slice_start > 1:
yield None
# Sliced range
yield from page_range[slice_start:slice_stop + 1]
# Rigth ellipsis
if slice_stop < last_index - 1:
yield None
yield page_range[-1]
# Small range test (no slicing)
assert list(slice_pagination_range(range(1, 6), 1, 1)) == [1, 2, 3, 4, 5]
assert list(slice_pagination_range(range(1, 6), 2, 1)) == [1, 2, 3, 4, 5]
assert list(slice_pagination_range(range(1, 6), 3, 1)) == [1, 2, 3, 4, 5]
assert list(slice_pagination_range(range(1, 6), 4, 1)) == [1, 2, 3, 4, 5]
assert list(slice_pagination_range(range(1, 6), 5, 1)) == [1, 2, 3, 4, 5]
# Medium range test (one ellipsis)
assert list(slice_pagination_range(range(1, 7), 1, 1)) == [1, 2, None, 6]
assert list(slice_pagination_range(range(1, 7), 2, 1)) == [1, 2, 3, None, 6]
assert list(slice_pagination_range(range(1, 7), 3, 1)) == [1, 2, 3, 4, None, 6]
assert list(slice_pagination_range(range(1, 7), 4, 1)) == [1, None, 3, 4, 5, 6]
assert list(slice_pagination_range(range(1, 7), 5, 1)) == [1, None, 4, 5, 6]
assert list(slice_pagination_range(range(1, 7), 6, 1)) == [1, None, 5, 6]
# Big range test (two ellipsis)
assert list(slice_pagination_range(range(1, 8), 1, 1)) == [1, 2, None, 7]
assert list(slice_pagination_range(range(1, 8), 2, 1)) == [1, 2, 3, None, 7]
assert list(slice_pagination_range(range(1, 8), 3, 1)) == [1, 2, 3, 4, None, 7]
assert list(slice_pagination_range(range(1, 8), 4, 1)) == [1, None, 3, 4, 5, None, 7]
assert list(slice_pagination_range(range(1, 8), 5, 1)) == [1, None, 4, 5, 6, 7]
assert list(slice_pagination_range(range(1, 8), 6, 1)) == [1, None, 5, 6, 7]
assert list(slice_pagination_range(range(1, 8), 7, 1)) == [1, None, 6, 7]
# More realistic scenario
assert list(slice_pagination_range(range(1, 30), 1, 3)) == [1, 2, 3, 4, None, 29]
assert list(slice_pagination_range(range(1, 30), 2, 3)) == [1, 2, 3, 4, 5, None, 29]
assert list(slice_pagination_range(range(1, 30), 3, 3)) == [1, 2, 3, 4, 5, 6, None, 29]
assert list(slice_pagination_range(range(1, 30), 4, 3)) == [1, 2, 3, 4, 5, 6, 7, None, 29]
assert list(slice_pagination_range(range(1, 30), 5, 3)) == [1, 2, 3, 4, 5, 6, 7, 8, None, 29]
assert list(slice_pagination_range(range(1, 30), 6, 3)) == [1, None, 3, 4, 5, 6, 7, 8, 9, None, 29]
assert list(slice_pagination_range(range(1, 30), 12, 3)) == [1, None, 9, 10, 11, 12, 13, 14, 15, None, 29]
assert list(slice_pagination_range(range(1, 30), 24, 3)) == [1, None, 21, 22, 23, 24, 25, 26, 27, None, 29]
assert list(slice_pagination_range(range(1, 30), 25, 3)) == [1, None, 22, 23, 24, 25, 26, 27, 28, 29]
assert list(slice_pagination_range(range(1, 30), 26, 3)) == [1, None, 23, 24, 25, 26, 27, 28, 29]
assert list(slice_pagination_range(range(1, 30), 27, 3)) == [1, None, 24, 25, 26, 27, 28, 29]
assert list(slice_pagination_range(range(1, 30), 28, 3)) == [1, None, 25, 26, 27, 28, 29]
assert list(slice_pagination_range(range(1, 30), 29, 3)) == [1, None, 26, 27, 28, 29]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment