聪明的排序(对可能包含数字的字符串进行排序)

3
我需要对一个可能包含数字的单元列表进行排序。
例如:["unit 1", "unit 2", ..., "unit 11"]。
大多数排序函数会按照这种顺序排序: unit 1,unit 11,unit 2..。
但我也可能有没有数字的情况。 ["apt A", "apt B", ..., "apt Z"]。
有没有聪明的解决方案可以正确地排序: unit 1, unit 2, ..., unit 11。 apt A, apt B, ..., apt Z。

整个列表将包含数字或字母吗,还是两者混合存在?如果它包含混合内容,则预期排序是什么? - Patrick Roberts
它可以包含混合的内容。我们希望首先按字母顺序排序,然后再按数字顺序排序。例如 [ "unit 1", "unit 2", "unit 11", "apt 1", "apt 2"] 应该排序为:[apt 1, apt 2, unit 1, unit 2, unit 11]。 - caden311
抱歉,我觉得我可能没有正确表达我的问题。['apt A', 'apt B', 'apt 1', 'apt 2'] 可以混合使用吗? - Patrick Roberts
是的,这是可能的。应该是这样的。['apt 1','apt 2','apt A','apt B'] - caden311
这通常被称为“自然排序”。也许你可以在现有的自然排序问题中找到答案。 - user2404501
1个回答

3

根据评论中的澄清,您可以通过/(\d+)/g将每个字符串拆分并按结果字符串数组中的每个元素进行排序。 将偶数索引视为字符串,奇数索引视为数字:

const input = ['unit 11', 'unit 1', 'unit 2', 'apt 11', 'apt 1', 'apt 2', 'unit A', 'unit c', 'unit B', 'apt a', 'apt C', 'apt b'];

function customSort (a, b) {
  a = a.toUpperCase().split(/(\d+)/g);
  b = b.toUpperCase().split(/(\d+)/g);

  const length = Math.min(a.length, b.length);

  for (let i = 0; i < length; i++) {
    const cmp = (i % 2)
      ? a[i] - b[i]
      : -(a[i] < b[i]) || +(a[i] > b[i]);

    if (cmp) return cmp;
  }

  return a.length - b.length;
}

console.log(input.sort(customSort));


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接