如何按指定子串列表对含下划线的Python字符串列表排序?
问题描述
现有字符串列表:
my_list = ['0123_abcd', '1234_bcde', '2345_cdef', '3456_defg', '4567_efgh']
需要按照另一个包含子串的列表排序:
ordering = ['3456', '2345', '0123']
要求:my_list中不在ordering对应的子串元素排在列表末尾,预期结果为:
result_list = ['3456_defg', '2345_cdef', '0123_abcd', '1234_bcde', '4567_efgh']
原代码在无后缀的列表中有效,但添加下划线和后缀后失效:
result_list = sorted(my_list, key=lambda e: (ordering.index(e),e) if e in ordering else (len(ordering),e))
尝试用split('_')[0]提取前缀但写法错误:
result_list = sorted(my_list, key=lambda e: e.split("_")[0] (ordering.index(e),e) if e in ordering else (len(ordering),e))
解决方案
核心问题是需提取每个元素下划线前的前缀,用该前缀匹配ordering列表,而非用整个元素判断。正确实现代码如下:
my_list = ['0123_abcd', '1234_bcde', '2345_cdef', '3456_defg', '4567_efgh'] ordering = ['3456', '2345', '0123'] result_list = sorted( my_list, key=lambda e: ( ordering.index(e.split('_')[0]), e ) if e.split('_')[0] in ordering else ( len(ordering), e ) )
关键说明
- 前缀提取:通过
e.split('_')[0]获取元素的前缀部分(如'3456_defg'提取为'3456'),确保能与ordering中的元素匹配。 - 排序键规则:
- 若前缀在
ordering内,排序键为(ordering.index(前缀), e):ordering.index(前缀)保证元素按指定顺序排列,e用于处理前缀重复时的次级排序。 - 若前缀不在
ordering内,排序键为(len(ordering), e):len(ordering)的值大于所有ordering的索引(索引从0开始),确保这部分元素排在指定顺序元素之后,e保证次级排序按元素自身字符串顺序。
- 若前缀在
性能优化
当ordering列表较大时,index()方法的时间复杂度为O(n),可将ordering转换为字典提升查找效率:
order_map = {val: idx for idx, val in enumerate(ordering)} result_list = sorted( my_list, key=lambda e: ( order_map.get(e.split('_')[0], len(order_map)), e ) )
使用order_map.get()直接获取前缀对应的索引,不存在时返回len(order_map),代码更简洁高效。
内容的提问来源于stack exchange,提问作者bla blub
相关产品推荐
相关产品推荐

