👻
[Bug #20911] #max にブロック引数を渡したときに意図しない挙動になるバグ報告
[Bug #20911] Array#max doesn't take block if using &:
- 次のように
#max
にブロックを渡すと数値に変換した値で比較した値が返ってきます
pp ["1", "2", "3"].max { |i| i.to_i }
# => "3"
- これが
&
渡しだとうまく動かない、というバグ報告になります
# error: no implicit conversion of String into Integer (TypeError)
pp ["1", "2", "3"].max(&:to_i)
- これなんですが
#max
のブロックでは2つの引数を受け取り、それを#<=>
で比較した値を返して並び替える、みたいな挙動になります - なので以下のように比較するのが正しいコードになります
# 正しく比較する場合はこう
pp ["111", "2", "13"].max { |a, b| a.to_i <=> b.to_i }
# => "111"
# i.to_i だけだとそもそもうまく並び替えできない
pp ["3", "2", "1"].max { |i| i.to_i }
# => "1"
pp ["111", "2", "13"].max { |i| i.to_i }
# => "3"
- また単純に
to_i
の値だけで並び替えしたい、のであれば#max_by
が利用できます
# ブロックの戻り値で並び替えを行う
pp ["111", "2", "13"].max_by { |i| i.to_i }
# => "111"
Discussion