配列要素(数字を含む文字列)のソート、自然ソート 質問する

配列要素(数字を含む文字列)のソート、自然ソート 質問する

次のような配列があります。

["IL0 Foo", "PI0 Bar", "IL10 Baz", "IL3 Bob says hello"]

そして、次のように表示されるように並べ替える必要があります。

["IL0 Foo", "IL3 Bob says hello", "IL10 Baz", "PI0 Bar"]

ソート機能を試してみました。

function compare(a,b) {
  if (a < b)
     return -1;
  if (a > b)
    return 1;
  return 0;
}

しかし、これは順序を与える

["IL0 Foo", "IL10 Baz", "IL3 Bob says hello", "PI0 Bar"]

機能する正規表現を考えようとしましたが、理解できません。役に立つかどうかはわかりません
が、形式は常に 2 文字、x 個の数字、任意の数の文字になります。

ベストアンサー1

これは「自然ソート」と呼ばれ、次のように JS で実装できます。

function naturalCompare(a, b) {
    var ax = [], bx = [];

    a.replace(/(\d+)|(\D+)/g, function(_, $1, $2) { ax.push([$1 || Infinity, $2 || ""]) });
    b.replace(/(\d+)|(\D+)/g, function(_, $1, $2) { bx.push([$1 || Infinity, $2 || ""]) });
    
    while(ax.length && bx.length) {
        var an = ax.shift();
        var bn = bx.shift();
        var nn = (an[0] - bn[0]) || an[1].localeCompare(bn[1]);
        if(nn) return nn;
    }

    return ax.length - bx.length;
}

/////////////////////////

test = [
    "img12.png",
    "img10.png",
    "img2.png",
    "img1.png",
    "img101.png",
    "img101a.png",
    "abc10.jpg",
    "abc10",
    "abc2.jpg",
    "20.jpg",
    "20",
    "abc",
    "abc2",
    ""
];

test.sort(naturalCompare)
document.write("<pre>" + JSON.stringify(test,0,3));

逆順に並べ替えるには、引数を入れ替えるだけです。

test.sort(function(a, b) { return naturalCompare(b, a) })

あるいは単に

test = test.sort(naturalCompare).reverse();

おすすめ記事