
本文介绍如何将已排序、无重复的整数列表高效转换为紧凑的文本表示(如 2,5-7,11-12),涵盖第三方库方案与纯 Python 实现,兼顾简洁性与可定制性。
本文介绍如何将已排序、无重复的整数列表高效转换为紧凑的文本表示(如 `2,5-7,11-12`),涵盖第三方库方案与纯 python 实现,兼顾简洁性与可定制性。
在处理日志范围、权限 ID 列表、时间戳分组等场景时,常需将连续整数序列压缩为人类可读的区间格式(例如 [19, 20, 21, 22] → "19-22"),而孤立数字则单独保留(如 [2] → "2")。给定输入 mylist = [2, 5, 6, 7, 11, 12, 19, 20, 21, 22, 37, 38, 40],目标输出为 "2,5-7,11-12,19-22,37-38,40"(注意末尾无逗号,但原文示例含逗号;实际应用中建议统一格式)。
✅ 推荐方案:使用 intspan 库(最简健壮)
intspan 是专为此类任务设计的轻量级库,支持解析、运算与格式化整数区间,API 清晰且经过充分测试:
from intspan import intspan mylist = [2, 5, 6, 7, 11, 12, 19, 20, 21, 22, 37, 38, 40] result = str(intspan(mylist)) # 输出: '2,5-7,11-12,19-22,37-38,40' print(result)
安装方式:pip install intspan。它自动识别连续段、处理边界、忽略重复,并支持反向解析(如 intspan("5-7,11,19-22")),适合生产环境。
⚙️ 纯 Python 实现(无需依赖)
若需避免外部依赖,可用一次遍历实现 O(n) 时间复杂度的区间合并:
def format_ranges(nums):
if not nums:
return ""
ranges = []
start = end = nums[0]
for num in nums[1:]:
if num == end + 1: # 连续
end = num
else: # 断开,保存上一段
ranges.append(f"{start}" if start == end else f"{start}-{end}")
start = end = num
# 添加最后一段
ranges.append(f"{start}" if start == end else f"{start}-{end}")
return ",".join(ranges)
# 测试
mylist = [2, 5, 6, 7, 11, 12, 19, 20, 21, 22, 37, 38, 40]
print(format_ranges(mylist)) # 输出: '2,5-7,11-12,19-22,37-38,40'
该函数逻辑清晰:维护当前区间的起始(start)和结束(end),遍历时判断是否连续;断开时将前一段加入结果,重置新区间。
⚠️ 注意事项与扩展建议
-
输入校验:
intspan和上述函数均假设输入已排序且无重复。若不确定,调用前请先执行sorted(set(nums))。 -
末尾逗号:原文示例含尾随逗号(
"2, 5-7, ... 40,"),但标准格式通常省略。如需强制加逗号,可改为",".join(ranges) + ","。 -
自定义分隔符:将
",".join(...)替换为"; ".join(...)即可适配不同分隔需求。 -
大数或负数支持:两种方案均原生支持负整数(如
[-3, -2, 0, 1, 2] → "-3--2,0-2"),注意双负号显示需额外处理(如用 Unicode 减号或空格分隔)。
综上,优先推荐 intspan —— 它是领域专用、稳定可靠的首选;纯 Python 版本则适用于教学、嵌入式或极简依赖场景。两者皆能精准表达“连续即压缩,孤立则单列”的核心语义。










