😎
Ruby で任意の要素を配列なら配列のまま、それ以外なら配列に変換する
何かしらの値を配列として扱いたい場合、通常は []
で囲むことが多いと思います。
[a]
このときに a
が配列だった場合、単純に []
で囲むとネストした配列になります。
a = [1, 2, 3]
[a] # => [[1, 2, 3]]
こういう場合に『配列だった場合は配列のまま』になってほしいことが稀によくあります。
Kernel.#Array
メソッドを利用する
こういうときに Kernel.#Array
を利用することで『配列は配列のまま、それ以外は配列に変換する』ということが実現することができます。
a = 42
# これは配列になる
p Array(a) # => [42]
b = [1, 2, 3]
# これは配列のまま
p Array(b) # => [1, 2, 3]
内部で呼び出されるメソッド
Array(a)
という呼び出しがあった場合は内部で次のような優先順位で処理されます。
-
a.to_ary
が呼び出さればその結果を返す - 次に
a.to_a
が呼び出さればその結果を返す - それでもなければ
[a]
を返す
class Array1
def to_a
["Array1"]
end
end
class Array2 < Array1
def to_ary
["Array2"]
end
end
# Array1#to_a が呼び出される
p Array(Array1.new)
# => ["Array1"]
# Array2#to_a ではなくて Array2#to_ary が優先して呼び出される
p Array(Array2.new)
# => ["Array2"]
また #to_ary
や #to_a
が配列でない場合は例外が発生します。
class Array1
def to_a
["Array1"]
end
end
class Array2 < Array1
def to_ary
["Array2"]
end
end
# Array1#to_a が呼び出される
p Array(Array1.new)
# => ["Array1"]
# Array2#to_a ではなくて Array2#to_ary が優先して呼び出される
p Array(Array2.new)
# => ["Array2"]
nil
を渡すとどうなる?
注意: Array(nil)
を渡した場合 []
が返ってきます。
p Array(nil) # => []
これは nil.to_a
が []
を返すからになります。
# nil.to_a は [] を返す
p nil.to_a # => []
仮に [nil]
を返してもらいたい場合は工夫する必要がありますねー。
注意: Hash オブジェクトを渡すとどうなる?
もう1個ぎょっとなる挙動なんですが Array(a: 1, b: 2)
は [[:a, 1], [:b, 2]]
になります。
p Array(a: 1, b: 2)
# => [[:a, 1], [:b, 2]]
これは Array(a: 1, b: 2)
は Array({ a: 1, b: 2 })
みたいに Hash
オブジェクトを渡したことになるんですが、これも Hash#to_a
が内部で呼び出されているからになります。
data = { a: 1, b: 2 }
p data.to_a
# => [[:a, 1], [:b, 2]]
# これも内部で data.to_a が呼び出される
p Array(data)
# => [[:a, 1], [:b, 2]]
これも Hash
のまま配列にするには工夫する必要がありますねー。
Discussion