排序混合字母/数字数组

IT技术 javascript jquery arrays sorting
2021-01-13 17:19:03

我有一个混合数组,我需要按字母然后按数字排序

[A1, A10, A11, A12, A2, A3, A4, B10, B2, F1, F12, F3]

我如何将其排序为:

[A1, A2, A3, A4, A10, A11, A12, B2, B10, F1, F3, F12]

我努力了

arr.sort(function(a,b) {return a - b});

但这只是按字母顺序排序。这可以用直接的 JavaScript 或 jQuery 来完成吗?

6个回答

var reA = /[^a-zA-Z]/g;
var reN = /[^0-9]/g;

function sortAlphaNum(a, b) {
  var aA = a.replace(reA, "");
  var bA = b.replace(reA, "");
  if (aA === bA) {
    var aN = parseInt(a.replace(reN, ""), 10);
    var bN = parseInt(b.replace(reN, ""), 10);
    return aN === bN ? 0 : aN > bN ? 1 : -1;
  } else {
    return aA > bA ? 1 : -1;
  }
}
console.log(
["A1", "A10", "A11", "A12", "A2", "A3", "A4", "B10", "B2", "F1", "F12", "F3"].sort(sortAlphaNum)
)

@Noitidart 偏好。两者应该没有区别。
2021-03-21 17:19:03
这是一个很好的答案,但它非常需要评论。我花了一些时间来阅读这篇文章并让它变得有意义。
2021-03-29 17:19:03
所以有点晚了……但是你不需要这个else块,因为第一个ifreturn如果aA === bA
2021-04-01 17:19:03
当然没有冒犯,因为它确实帮助了我。+1。
2021-04-02 17:19:03
@epascarello 当我找到它时,我真的很感激它 - 当你第一次看到它时,它只是有点令人困惑。它很简洁,但没有按主题命名,如果您不熟悉正则表达式、三元或一般排序,那么理解起来有点飞跃。字母数字排序是一个非常常见的问题,提出这个问题只需要粗略的数组知识,因此假设更多的知识会让人们要求评论。这是一个很好的答案和您的特权,但描述可能会让每个感兴趣的人更容易消化。
2021-04-11 17:19:03
const sortAlphaNum = (a, b) => a.localeCompare(b, 'en', { numeric: true })

用法:

const sortAlphaNum = (a, b) => a.localeCompare(b, 'en', { numeric: true })
console.log(['A1', 'A10', 'A11', 'A12', 'A2', 'A3', 'A4', 'B10', 'B2', 'F1', 'F12', 'F3'].sort(sortAlphaNum))

给出:

["A1", "A2", "A3", "A4", "A10", "A11", "A12", "B2", "B10", "F1", "F3", "F12"]

您可能需要将'en'参数更改为您的语言环境或以编程方式确定,但这适用于英文字符串。

localeCompare IE11、Chrome、Firefox、Edge 和 Safari 10 支持。

这应该是 IMO 接受的答案。小 nit:第一行在 { numeric: true }) 之后包含一个尾随反引号
2021-03-24 17:19:03
此处显示的这种内置字母数字比较很方便,但结果证明它非常慢。公认的解决方案快 3 倍,但有时确实会给出错误的答案。正如我在那里评论的那样,我的代码得到了正确的答案并且再次快了 5 倍,所以它比这个解决方案快 15 倍。请参阅alphanum.timkay.com/cmpalphanum.js?run=edit
2021-03-31 17:19:03

我有类似的情况,但是,混合了字母数字和数字,需要先对所有数字进行排序,然后是字母数字,所以:

A10
1
5
A9
2
B3
A2

需要成为:

1
2
5
A2
A9
A10
B3

我能够使用提供的算法并对其进行更多修改以完成此操作:

var reA = /[^a-zA-Z]/g;
var reN = /[^0-9]/g;
function sortAlphaNum(a,b) {
    var AInt = parseInt(a, 10);
    var BInt = parseInt(b, 10);

    if(isNaN(AInt) && isNaN(BInt)){
        var aA = a.replace(reA, "");
        var bA = b.replace(reA, "");
        if(aA === bA) {
            var aN = parseInt(a.replace(reN, ""), 10);
            var bN = parseInt(b.replace(reN, ""), 10);
            return aN === bN ? 0 : aN > bN ? 1 : -1;
        } else {
            return aA > bA ? 1 : -1;
        }
    }else if(isNaN(AInt)){//A is not an Int
        return 1;//to make alphanumeric sort first return -1 here
    }else if(isNaN(BInt)){//B is not an Int
        return -1;//to make alphanumeric sort first return 1 here
    }else{
        return AInt > BInt ? 1 : -1;
    }
}
var newlist = ["A1", 1, "A10", "A11", "A12", 5, 3, 10, 2, "A2", "A3", "A4", "B10", "B2", "F1", "F12", "F3"].sort(sortAlphaNum);
["a25b", "ab", "a37b"]将产生[ "a25b", "ab", "a37b" ]而不是[ "a25b", "a37b", "ab" ].
2021-03-23 17:19:03

一个简单的方法是使用https://www.w3schools.com/jsref/jsref_localecompare.asp的 localeCompare() 方法JavaScript

例子:

export const sortAlphaNumeric = (a, b) => {
    // convert to strings and force lowercase
    a = typeof a === 'string' ? a.toLowerCase() : a.toString();
    b = typeof b === 'string' ? b.toLowerCase() : b.toString();

    return a.localeCompare(b);
};

预期行为:

1000X Radonius Maximus
10X Radonius
200X Radonius
20X Radonius
20X Radonius Prime
30X Radonius
40X Radonius
Allegia 50 Clasteron
Allegia 500 Clasteron
Allegia 50B Clasteron
Allegia 51 Clasteron
Allegia 6R Clasteron
Alpha 100
Alpha 2
Alpha 200
Alpha 2A
Alpha 2A-8000
Alpha 2A-900
Callisto Morphamax
Callisto Morphamax 500
Callisto Morphamax 5000
Callisto Morphamax 600
Callisto Morphamax 6000 SE
Callisto Morphamax 6000 SE2
Callisto Morphamax 700
Callisto Morphamax 7000
Xiph Xlater 10000
Xiph Xlater 2000
Xiph Xlater 300
Xiph Xlater 40
Xiph Xlater 5
Xiph Xlater 50
Xiph Xlater 500
Xiph Xlater 5000
Xiph Xlater 58
商品订购不正确!例如,1000X 应该在 10X 之后。
2021-03-16 17:19:03
这应该是答案。好的!
2021-03-29 17:19:03

您可以使用 Intl.Collator

Read here 相比,它具有性能优势localeCompare

浏览器可比性(所有浏览器都支持)

let arr = ["A1", "A10", "A11", "A12", "A2", "A3", "A4", "B10", "B2", "F1", "F12", "F3"]

let op = arr.sort(new Intl.Collator('en',{numeric:true, sensitivity:'accent'}).compare)

console.log(op)

我尝试在 Node.js 中对此进行基准测试,它比 localeCompare 答案快得多。我测试了 1000 多次迭代,localeCompare 用了 3.159 秒,这个 Intl.Collat​​or 在相同条件下只用了 200.178ms,非常令人印象深刻。
2021-04-05 17:19:03