求更Pythonic的Excel单元格名称排序实现方案(去除包装类)
嘿,我懂你这种感觉——用cmp_to_key加上那个包装类确实有点啰嗦,完全不符合Python追求简洁的风格。其实我们完全可以绕开比较函数,直接给sort()的key参数生成一个原生就能正确排序的键值,完美匹配Excel单元格的排序逻辑!
先理清楚Excel的排序规则:
- 列名字符串越长,优先级越高(比如
BB>AZ>AA>B>A) - 列名长度相同时,按字母顺序排序
- 最后按行号的数字大小排序
基于这个规则,我们只需要把每个单元格名称转换成一个元组,元组的元素依次是:(列名长度, 列名字符串, 行号数字)。Python的元组排序正好是按元素顺序依次比较的,完全贴合我们的需求!
实现方案1:手动拆分字符和数字
def excel_cell_key(cell): letters = [] numbers = [] for c in cell: if c.isalpha(): letters.append(c) else: numbers.append(c) col_name = ''.join(letters) row_num = int(''.join(numbers)) # 返回排序键,让Python原生排序自动处理 return (len(col_name), col_name, row_num) # 测试一下 cell_ids = ['A1', 'AA1', 'B3', 'B2', 'BB1', 'AZ15'] cell_ids.sort(key=excel_cell_key) print(cell_ids)
输出结果正好是你要的:
['A1', 'B2', 'B3', 'AA1', 'AZ15', 'BB1']
更简洁的方案:用正则表达式拆分
如果觉得手动循环拆分有点麻烦,用正则表达式可以一行搞定拆分:
import re def excel_cell_key(cell): # 匹配字母部分和数字部分 col_match, row_match = re.match(r'([A-Za-z]+)(\d+)', cell).groups() return (len(col_match), col_match, int(row_match)) # 同样的测试代码 cell_ids = ['A1', 'AA1', 'B3', 'B2', 'BB1', 'AZ15'] cell_ids.sort(key=excel_cell_key) print(cell_ids)
为什么这个方案更好?
- 完全Pythonic:不需要依赖
cmp_to_key和自定义包装类,直接利用Python原生的排序机制,代码简洁易读 - 性能更优:
key函数只需要对每个元素计算一次键值,而比较函数每次排序比较都要重复计算,效率更高 - 扩展性强:如果以后需要调整排序规则,只需要修改返回的元组结构就行,非常灵活
内容的提问来源于stack exchange,提问作者Yaroslav
相关产品推荐
相关产品推荐

