たとえば、こんな配列とHashがあったとする。
keys = %w[hoge bar] hash = { 'hoge'=> 'ほげ', 'aaa'=> 'あああ', 'bar'=> 'ばあー'}
keys配列の各要素をkeyとして、hashからそれぞれ対応するキーとバリューを取得したいときはHash#slice
を使うと便利。
> hash.slice(*keys) => {"hoge"=>"ほげ", "bar"=>"ばあー"}
*keys
としているところに注意。
たとえば、こんな配列とHashがあったとする。
keys = %w[hoge bar] hash = { 'hoge'=> 'ほげ', 'aaa'=> 'あああ', 'bar'=> 'ばあー'}
keys配列の各要素をkeyとして、hashからそれぞれ対応するキーとバリューを取得したいときはHash#slice
を使うと便利。
> hash.slice(*keys) => {"hoge"=>"ほげ", "bar"=>"ばあー"}
*keys
としているところに注意。
たとえば以下の配列から、初めに見つかった3の倍数を取り出したいとき。
nums = [1, 2, 3, 4, 5, 6, 7, 8, 9]
select
を使うとこうなる。
> nums.select { |num| (num % 3).zero? }.first => 3
これでも期待するデータを取得できるが、配列内のすべての要素をチェックしているため効率が悪い。最後のfirst
がそれを物語っている。first
を取り除いてみると、
> nums.select{|num| (num % 3).zero? } => [3, 6, 9]
となり、やはりすべての要素をチェックして無駄な配列を作っている。
こういった場合はfind
のほうが効率的だ。
> nums.find { |num| (num % 3).zero? } => 3
最初に3の倍数を見つけて、そこで探索を終了する。
flat_map
がflatten.map
を省略したものだと勘違いしていた話。
ここにネストした配列がある。
> arr = [[1,2], [3,4]] => [[1, 2], [3, 4]]
flatten
すると、平坦な配列になる。
> arr.flatten => [1, 2, 3, 4]
flatten
した後にmap
して各要素を2倍にしたいときはこうなる。
> arr.flatten.map { |num| num * 2 } => [2, 4, 6, 8]
では、flatten.map
をflat_map
に置き換えるとどうなるか?
> arr.flat_map { |num| num * 2 } => [1, 2, 1, 2, 3, 4, 3, 4]
flatten.map
と同じ結果にはなっていない。
> arr.flatten.map { |num| num * 2 } => [2, 4, 6, 8] > arr.flat_map { |num| num * 2 } => [1, 2, 1, 2, 3, 4, 3, 4]
flat_map
のとき、numには何が渡ってくるのか?
> arr.flat_map { |num| p num } [1, 2] [3, 4]
ネストした配列を取得していることがわかった。arr.flat_map { |num| num * 2 }
の挙動としては、
> [1, 2] * 2 => [1, 2, 1, 2] > [3, 4] * 2 => [3, 4, 3, 4]
をしてから、返り値を連結した配列を返す。
> arr.flat_map { |num| num * 2 } => [1, 2, 1, 2, 3, 4, 3, 4]
よって、さきほどのflatten.map
と同じ結果にしたいならこう書く必要がある。
> arr.flat_map { |arr| arr.map { |num| num * 2}} => [2, 4, 6, 8] > arr.flatten.map { |num| num * 2 } => [2, 4, 6, 8]
まとめると、Ruby のflat_map
はflatten.map
と同じ挙動にはならない。ちなみにflat_map
のエイリアスメソッドとしてcollect_concat
が存在する。
参考