Краткое решение, которое работает без дополнительного импорта. Он принимает любые итерируемые, сортирует несортированные данные и удаляет повторяющиеся элементы:
def ranges(nums):
nums = sorted(set(nums))
gaps = [[s, e] for s, e in zip(nums, nums[1:]) if s+1 < e]
edges = iter(nums[:1] + sum(gaps, []) + nums[-1:])
return list(zip(edges, edges))
Пример:
>>> ranges([2, 3, 4, 7, 8, 9, 15])
[(2, 4), (7, 9), (15, 15)]
>>> ranges([-1, 0, 1, 2, 3, 12, 13, 15, 100])
[(-1, 3), (12, 13), (15, 15), (100, 100)]
>>> ranges(range(100))
[(0, 99)]
>>> ranges([0])
[(0, 0)]
>>> ranges([])
[]
Это то же самое, что и решение @ dansalmo , которое мне показалось удивительным, хотя и немного сложным для чтения и применения (поскольку оно не дано как функция).
Обратите внимание, что его можно легко изменить, чтобы он выплевывал "традиционные" открытые диапазоны [start, end)
, например, изменение оператора возврата:
return [(s, e+1) for s, e in zip(edges, edges)]
Я скопировал этот ответ из другого вопроса , который был помечен как дубликат этого с целью облегчить его поиск (после того, как я только что снова искал эту тему, найдя только вопрос здесь сначала и не удовлетворены ответами).