0

特定の方法で並べ替える必要がある奇妙な配列がありますが、多くの手作業なしで実行できるかどうかはわかりません。

配列を考えてみましょう:[ '1a', '2a', '2aa', '5-6', '1', '2', '3', '20' , '7', '8']

文字列の配列です。正しくソートすると、次のようになります。

[ '1', '1a', '2', '2a', '2aa', '3', '5-6', '7', '8', '20' ]

アウトライン番号付けシステムのようなものだと考えてください。

その順番で並べ替えるにはどうすればよいですか?

これは、通常の並べ替えがデフォルトの辞書編集動作でどのように処理するかを示すjsfiddleです(実際には、必要なものにかなり近いです):

http://jsfiddle.net/qkE9m/

私は node.js で作業しており、underscore.js を自由に使用できます。

4

2 に答える 2

1

わかりました、これがこの問題を解決するための私の試みです。現在、コードはかなり冗長ですが、縮小する方法を検討しており、回答を更新します。ただし、これで問題が解決するはずです。それがあなたのenvであるため、コードをノードモジュールとして投稿します。

その要点は、アイテムを個別にソートできる個別のパーツに分割することです。これらの配列のそれぞれを並行してループし、不一致を見つけると、基本的なソート比較を実行します。

sorter.js

// regex patterns to determine how to "parse" an input item
var patterns = [
    /^([a-zA-Z]+)$/,                      // only letters
    /^(\d+)$/,                          // only contains an integer
    /^(\d+)\-\d+$/,                     // contains 2 integers separated by a hyphen
    /^(\d+)([a-z]+)?\-(\d+)([a-z]+)?$/, // contains a 2 integer/letter combos separated by a hyphen
    /^(\d+)([a-z]+)$/                   // contains an integer followed by letters
];

function itemComparator(item) {
    var len = patterns.length,
        matches, x, regex;

    for (x = 0; x < len; x++) {
        regex = patterns[x];
        if (regex.test(item)) {
            matches = item.match(regex).slice(1);
            if (/^\d+$/.test(matches[0])) {
                matches[0] = parseInt(matches[0], 10);
            }
            return matches;
        }
    }

    throw new Error("could not parse item for comparison: " + item);
}

module.exports = function (a, b) {
    var compA = itemComparator(a),
        compB = itemComparator(b),
        x, len, tmpA, tmpB, typeA, typeB; // tmp vars

    // find the largest size, so we don't miss anything
    len = Math.max(compA.length, compB.length);

    // loop each comp arr in parallel
    for (x = 0; x < len; x += 1) {
        // store for speed
        tmpA = compA[x];
        tmpB = compB[x];
        typeA = typeof tmpA;
        typeB = typeof tmpB;

        // if the elements are not equal
        if (tmpA !== tmpB) {
            // then do the comparison, and stop the loop
            if (typeA === typeB) {
                return tmpA < tmpB ? -1 : 1;
            } else if (typeA === "undefined") {
                return -1;
            } else if (typeB === "undefined") {
                return 1;
            } else if (typeA === "string") {
                return -1;
            } else if (typeB === "string") {
                return 1;
            } else {
                console.warn("unexpected condition for %s (%s) and %s (%s)", tmpA, typeA, tmpB, typeB);
                return 0;
            }
        }
    }
};

test.js

var sorter = require("./sorter"),
    arr = [
        '1a', 'aa', '2a', '2aa', '5-6', '1', '2', '3', 'DBA', 'bb',
        '20', '2b', '7', '8', '125a', '33a-35', 'ABC',
        '3aaa-4c', '3aaa-52d', 'AA', 'c', '5dd', 'aa'
    ];

console.log(arr.sort(sorter));

// [ 'AA',
//   'ABC',
//   'DBA',
//   'aa',
//   'aa',
//   'bb',
//   'c',
//   '1',
//   '1a',
//   '2',
//   '2a',
//   '2aa',
//   '2b',
//   '3',
//   '3aaa-4c',
//   '3aaa-52d',
//   '5-6',
//   '5dd',
//   '7',
//   '8',
//   '20',
//   '33a-35',
//   '125a' ]
于 2012-11-02T17:13:35.403 に答える
0

実際のデータがどのように見えるかはわかりませんが、これで正しい方向に進むはずです。

[ '1a', '2a', '2aa', '5-6', '1', '2', '3', '20' , '7', '8'].sort(function(a,b)
{
    if (parseFloat(a) !== parseFloat(b))
    {
        return parseFloat(a) - parseFloat(b);
    }
    if (a.charAt(0) !== b.charAt(0))
    {//just to be on the safe side
        return +(a[0]) - +(b[0]);
    }
    return a.length - b.length;
});
//result:
["1", "1a", "2", "2a", "2aa", "3", "5-6", "7", "8", "20"]
于 2012-11-02T16:30:50.040 に答える