9

数値または文字列値が混在している可能性のある値の配列をソートしようとしています (例: [10,"20",null,"1","bar","-2",-3,null,5,"foo"])。この配列を次のように並べ替えるにはどうすればよいですか

  • null値は常に最後に配置されます (ソート順に関係なく、jsFiddle を参照してください)。
  • 負の数は正しくソートされます (つまり、それらは正の数よりも小さく、それらの間で正しくソートされます)

? 詳細な数値と文字列の例 (およびオプションを使用) を使用してjsFiddleを作成しましたが、出発点として以下に並べ替えアルゴリズムの数値バージョンを貼り付けます。localeComparenumeric

// Sorting order
var order = "asc"; // Try switching between "asc" and "dsc"

// Dummy arrays
var numericArr = [10,20,null,1,-2,-3,null,5];

// Sort arrays
$(".output1").append(numericArr.toString());
numericArr.sort(sortByDataNumeric);
$(".output2").append(numericArr.toString());

// Numeric sorting function
function sortByDataNumeric(a, b, _order) {

    // Replace internal parameters if not used
    if (_order == null) _order = order;

    // If values are null, place them at the end
    var dflt = (_order == "asc" ? Number.MAX_VALUE : -Number.MAX_VALUE);

    // Numeric values
    var aVal = (a == null ? dflt : a);
    var bVal = (b == null ? dflt : b);
    return _order == "asc" ? (aVal - bVal) : (bVal - aVal);
}

私の文字列ソート アルゴリズム ( jsFiddleを参照) の問題は、値を常に最後に配置する方法を見つけることができずnull、負の値がそれ自体で正しくソートされないことです (たとえば、-3 は -2 よりも小さい必要があります)。

編集

コメントに答えるために、私は[10,"20",null,"1","bar","-2",-3,null,5,"foo"]ソートすることを期待しています[-3,"-2","1",5,10,"20","bar","foo",null,null]

4

4 に答える 4

11

最初にどちらかの値であるかどうかを確認しnull、反対の値を返す必要があります。


余談ですが:

デフォルト値については、その値を と比較するので_orderはなく、パラメータが であるかどうかを確認する必要があります。未定義のものを直接比較しようとすると、参照エラーが発生します。undefinednull

(undefinedVar == null) // ReferenceError: undefinedVar is not defined

代わりに、変数が未定義かどうかを確認する必要があります。

(typeof undefinedVar == "undefined") // true

また、グローバル順序変数に依存するのではなく、比較関数をクロージャでラップすることをお勧めします。

時々のように:

[].sort(function(a, b){ return sort(a, b, order)})

このようにして、インスタンスごとのレベルで並べ替えることができます。


http://jsfiddle.net/gxFGN/10/

JavaScript

function sort(a, b, asc) {
    var result;

    /* Default ascending order */
    if (typeof asc == "undefined") asc = true;

    if (a === null) return 1;
    if (b === null) return -1;
    if (a === null && b === null) return 0;

    result = a - b;

    if (isNaN(result)) {
        return (asc) ? a.toString().localeCompare(b) : b.toString().localeCompare(a);
    }
    else {
        return (asc) ? result : -result;
    }
}
于 2013-09-30T22:33:53.030 に答える
2
function sortByDataString(a, b) {
    if (a === null) {
        return 1;
    }
    if (b === null) {
        return -1;
    }
    if (isNumber(a) && isNumber(b)) {
        if (parseInt(a,10) === parseInt(b,10)) {
            return 0;
        }
        return parseInt(a,10) > parseInt(b,10) ? 1 : -1;
    }
    if (isNumber(a)) {
        return -1;
    }
    if (isNumber(b)) {
        return 1;
    }
    if (a === b) {
        return 0;
    }
    return a > b ? 1 : -1;
}

ここでフィドル:http://jsfiddle.net/gxFGN/6/

order パラメーターは省略しましたが、必要に応じて配列を最後に逆にすることもできます。

于 2013-09-30T19:54:07.060 に答える
1

これを使って:

function typeOrder(x) {
    if (x == null)
        return 2;
    if (isNaN(+x))
        return 1;
    return 0;
}
function sortNumber(a, b) {
    a = parseInt(a, 10); b = parseInt(b, 10);
    if (isNaN(a) || isNaN(b))
        return 0;
    return a - b;
}
function sortString(a, b) {
    if (typeof a != "string" || typeof b != "string")
       return 0;
    return +(a > b) || -(b > a);
}

order = order == "dsc" ? -1 : 1;
numericArr.sort(function(a, b) {
    return order * ( typeOrder(a)-typeOrder(b)
                     || sortNumber(a, b)
                     || sortString(a, b)
                   );
});

更新されたフィドル

于 2013-09-30T20:45:15.450 に答える
0

あなたの問題は赤いニシンであると確信しています...あなたが貼り付けた抽象関数sortは3番目のパラメーターを取得しません(あなたの場合は_order)。したがって、あなたの状況では、常にundefined.

それを念頭に置いてコードを再検討し、何が得られるかを確認してください。

指定した配列は完全に数値であるため、並べ替えは正しく機能するはずですが、他のコメント投稿者が示唆しているように、配列が文字列値 (つまり、「10」、「-7」など) で終わった場合は、parseInt とテストが必要です。比較を行う前に isNaN の場合。

于 2013-09-30T19:09:05.763 に答える