Ruby中如何对字符串数组先按字母分组再按数字排序?
解决方案
核心思路
要实现需求,需要分两步处理:
- 保留原分组顺序:基于原数组已按字母排序的特点,按前缀(如
Cat、Goal、Target)分组,且分组顺序严格遵循原数组中前缀首次出现的顺序,不能重新对分组键排序。 - 组内自然排序:对每个分组内的元素,拆分出后缀部分,区分数字和非数字类型分别排序——数字按数值大小排序,非数字按字符串自然顺序排序。
JavaScript 实现代码
const originalArray = ["Cat 2", "Goal A", "Goal B", "Goal C", "Target 1", "Target 11", "Target 4"]; // 1. 构建分组并记录分组顺序 const groups = new Map(); const groupOrder = []; originalArray.forEach(item => { // 拆分前缀和后缀(仅按第一个空格分割,兼容含多空格的元素) const [prefix, suffix] = item.split(' ', 2); if (!groups.has(prefix)) { groups.set(prefix, []); groupOrder.push(prefix); // 记录前缀首次出现的顺序,保持原字母分组结构 } groups.get(prefix).push({ item, suffix }); }); // 2. 对每组排序并拼接结果 const result = []; groupOrder.forEach(prefix => { const group = groups.get(prefix); group.sort((a, b) => { const aIsNumber = !isNaN(Number(a.suffix)); const bIsNumber = !isNaN(Number(b.suffix)); if (aIsNumber && bIsNumber) { return Number(a.suffix) - Number(b.suffix); // 数字按数值排序 } return a.suffix.localeCompare(b.suffix); // 非数字按字符串自然排序 }); result.push(...group.map(el => el.item)); }); console.log(result); // 输出:["Cat 2", "Goal A", "Goal B", "Goal C", "Target 1", "Target 4", "Target 11"]
Python 实现代码
original_array = ["Cat 2", "Goal A", "Goal B", "Goal C", "Target 1", "Target 11", "Target 4"] # 1. 分组并记录分组顺序 groups = {} group_order = [] for item in original_array: prefix, suffix = item.split(' ', 1) if prefix not in groups: groups[prefix] = [] group_order.append(prefix) groups[prefix].append((suffix, item)) # 2. 对每组排序并拼接结果 result = [] for prefix in group_order: # 排序规则:数字转int排序,非数字按字符串排序 sorted_group = sorted(groups[prefix], key=lambda x: int(x[0]) if x[0].isdigit() else x[0]) result.extend([item for (suffix, item) in sorted_group]) print(result) # 输出:['Cat 2', 'Goal A', 'Goal B', 'Goal C', 'Target 1', 'Target 4', 'Target 11']
关键细节说明
- 分组顺序的保留:通过
groupOrder数组记录前缀首次出现的顺序,确保最终结果的分组结构和原数组的字母排序分组完全一致,不会出现Cat组被移到后面的情况。 - 兼容多种后缀类型:代码同时支持数字后缀(如
Target 1)和字母后缀(如Goal A)的排序需求,无需额外修改即可适配不同场景。
内容的提问来源于stack exchange,提问作者Maxime
相关产品推荐
相关产品推荐

