问题是你不能将字符串与整数进行比较:
> 2<"2"
(irb):15:in `<': comparison of Integer with String failed (ArgumentError)
解决方法(以您的具体示例为例)是让array 表现得好像它是所有字符串一样。
给定:
array = ["_", 2, 3, "_"]
如果你只希望结果是一个统一的字符串数组:
> array.map{|e| e.to_s}.sort
=> ["2", "3", "_", "_"]
如果您希望元素保持其类型:
> array.map{|e| [e.to_s, e]}.sort.map{|e| e[1]}
=> [2, 3, "_", "_"]
或者,或者:
> array.sort_by{|e| e.to_s}
=> [2, 3, "_", "_"]
这里的潜在问题是,如果您仅依赖于转换为字符串(解决了您给出的示例),您将得到一个不好的整数结果:
> array = ["10", 12, 3, "0", "b", "a"]
=> ["10", 12, 3, "0", "b", "a"]
> array.sort_by{|e| e.to_s}
=> ["0", "10", 12, 3, "a", "b"] # desirable?
使用.to_i 不能完全解决这个问题:
> array.sort_by{|e| e.to_i}
=> ["0", "b", "a", 3, "10", 12] # fixed?
这可能最好通过对两者进行排序来解决:
> array.sort_by{|e| [e.to_i, e.to_s]}
=> ["0", "a", "b", 3, "10", 12]
幸运的是,Ruby 让选择变得超级容易。
请注意,.sort_by 或其他enumerable sorts 不是 stable sort,因此比较相等的元素可能会以与给定不同的顺序返回:
> array=[1,2,3,4,5,6,7,8,9]
=> [1, 2, 3, 4, 5, 6, 7, 8, 9]
> array.sort_by{|e| 0} # make them all compare equal
=> [9, 2, 3, 4, 5, 6, 7, 8, 1]
现在要修复那个,添加一个索引:
> array.each_with_index.sort_by{|e,i| [0,i]}.map(&:first)
=> [1, 2, 3, 4, 5, 6, 7, 8, 9]
或者,正如 cmets 中指出的那样:
> array.sort_by.with_index { |e, i| [0, i] }
=> [1, 2, 3, 4, 5, 6, 7, 8, 9]