移転しました。

JavaScriptの配列を数値でソートする

JavaScriptのArrayオブジェクトには組み込みで、sortメソッドが用意されている。でも、sortメソッドは文字列としてソートしてしまうので、要素が全て数字で数字順に並び替えるときには使えない。
例えば、

var test = new Array(10,0,5);
test.sort();
alert(test);

の結果は「0,10,5」となってしまう。
対応策は、人力検索の質問に回答があって、並び順を指定する関数を渡せば良いとのこと。

var test = new Array(10,0,5);
test.sort(function(a, b) {
  return (parseInt(a) > parseInt(b)) ? 1 : -1;
});
alert(test);

これで結果が「0,5,10」となる。
Arrayオブジェクトのプロトタイプに追加してしまうとこんな感じか。

Array.prototype.sortByNumber = function() {
  this.sort(function(a, b) {
    return (parseInt(a) > parseInt(b)) ? 1 : -1;
  });
}

これで全然問題ないのだけど、最近まともにプログラム書いてないので、リハビリがてらに数値ソートを自作してみた。

Array.prototype.sortByNumber = function() {
  var ori = this;
  var res = new Array();
  for (var i = 0; i < ori.length; i++) {
    var x = ori[i];
    if (typeof x != "number") {
      return false;
    }
    // Array.length == 0.
    if (res.length == 0) {
      res[0] = x;
    // Array.length == 1.
    } else if (res.length == 1) {
      if (x > res[0]) {
        res[1] = x;
      } else {
        var tmp = res[0];
        res[0] = x;
        res[1] = tmp;
      }
    // Array.length > 2.
    } else {
      var buf = new Array();
      // Min
      if (x <= res[0]) {
        buf[0] = x;
        for (var rk = 0; rk < res.length; rk++) {
          buf[buf.length] = res[rk];
        }
        res = buf;
      // Max
      } else if (x >= res[res.length - 1]) {
        res[res.length] = x;
      // Between
      } else {
        var index;
        for (var rk = 0; rk < res.length; rk++) {
          var here = res[rk];
          var next = res[rk + 1];
          if (x >= here && x <= next) {
            index = rk + 1;
          }
        }
        for (var rk = 0; rk < index; rk++) {
          buf[buf.length] = res[rk];
        }
        buf[buf.length] = x;
        for (var rk = index; rk < res.length; rk++) {
          buf[buf.length] = res[rk];
        }
        res = buf;
      }
    }
  }
  return res;
}

// Test code.
var test = new Array(
  20,1,-1,4,10,3,12,11,2,100,11.124,22,43,-50,3.5
);
alert(test.sortByNumber());

ちなみに、ベンチを取ると明らかに組み込みのsortを使ったほうが速いので、リハビリコードは使わないようにしましょう。