>>> [5,10,2,4,30].sort(); [10, 2, 30, 4, 5]
えー、なにそれー
compareFunction (比較関数) が与えられなかった場合、要素はそれぞれの文字列に変換したものを比較して辞書 (あるいは電話帳。数的でない) 順にソートされます。例えば、"80" は辞書順では "9" の前に来ますが、数的なソートでは 9 が 80 の前に来ます。
そ、そうなのか。
ECMA-262 5th EditionによるとArray.prototype.sortの比較操作は
13. If the argument comparefn is not undefined, then a.If IsCallable(comparefn) is false, throw a TypeError exception. b.Return the result of calling the [[Call]] internal method of comparefn passing undefined as the this value and with arguments x and y. 14. Let xString be ToString(x). 15. Let yString be ToString(y). 16. If xString < yString, return −1. 17. If xString > yString, return 1. 18. Return +0.
比較関数を渡さない場合は文字列として比較する仕様らしい。数値で比較したいなら比較関数を渡せと。
>>> [5,10,2,4,30].sort(function(a,b){return a-b}); [2, 4, 5, 10, 30]
ま、JavaScriptは文字列と数値の境目にあいまいなところがあるので、文字列で比較というのは無難なのかもしれないな…
>>> ["12",10,"11",13, 9, "8",7].sort(); [10, "11", "12", 13, 7, "8", 9]
そういえば、Rubyはどうなんだろう?
irb(main):001:0> ["12",10,"11",13, 9, "8",7].sort ArgumentError: comparison of Fixnum with String failed from (irb):1:in `sort' from (irb):1
JavaScriptほど型に甘くない。
Rubyはsort_byを使ってIntegerとして比較するかStringとして比較するか決められる。
irb(main):003:0> ["12",10,"11",13, 9, "8",7].sort_by{|i| i.to_i } => [7, "8", 9, 10, "11", "12", 13] irb(main):004:0> ["12",10,"11",13, 9, "8",7].sort_by{|i| i.to_s } => [10, "11", "12", 13, 7, "8", 9]
ま、普通はmapとかで型をそろえるだろうな
irb(main):006:0> ["12",10,"11",13, 9, "8",7].map{|i| i.to_i }.sort => [7, 8, 9, 10, 11, 12, 13]
ついき
最近使ってなくてすっかり忘れてたけどperlも文字列の辞書順でソートだった。別にJavaScriptが特別変わっているというわけじゃないすね…
$ perl -e "print join(',', sort (10,2,'30',4,50))" 10,2,30,4,50 $ perl -e "print join(',', sort { $a <=> $b }(10,2,'30',4,50))" 2,4,10,30,50