Ruby
Rails

使うか分からない、だが俺は使った、便利なRuby, Rails 配列編集テクニック5選

Rubyは便利なメソッドがたくさんある。。。。

Rubyには便利なメソッドがたくさんありますよね。
Ruby書いて、他の言語を触るとRubyだったらこのメソッドが使えるのに。。。
ってなることも少なくないと思います。

しかし、便利なメソッドがありすぎて把握しきれないのも事実だと思うのです。
僕の場合、Rubyのメソッドがあれば一発でやってくれるちょっと凝った配列の処理を
eachやら、forやらで散々書いていたこともあります。

ということで、今回は実際にプロダクト内で僕が使った、

そんなには頻繁につかわない、だがこれは便利!という

Rubyの配列メソッド、テクニックたちをここに置いて置こうと思います。

2次元配列でサンプル、デフォルトデータを挿入

こんな状況はありませんでしょうか??
2次元配列の要素で、空配列とそうでない配列が混在している。
この状況で、空の配列にはサンプルデータを突っ込みたい。

状況のイメージはこんな感じです。

[['data1_01','data1_02'], ['data2_02'], []]

[['data1_01','data1_02'], ['data2_02'], ['sample_data']]

そんな時に便利なのが、 presenceメソッド と||演算。
実際はこんな感じで使いました。

array = [['data_01'], ['data_02'], []]

array.map { |ele| ele.presence || ['sample_data'] }

=> [['data_01'], ['data_02'], ['sample_data']]

presenceメソッドはActiveRecordのメソッド、presence?の返り値がtrueの場合はレシーバ自体を返し、falseの場合はnilを返すメソッドです。

|| 演算は左辺がfalseの場合は右辺の値を返す演算子です。Rubyでbool値がfalseになるオブジェクトはnilのみなので、以下の様によく変数に値が入っていなければ再代入したい場合などにも使われます。

arg ||= 'data'

イテレータを使う際のnilによるno method errorを回避したい

each などを使う際に、たまにレシーバーがnilの場合があって、no method error が出る時ありませんか??

具体的には

def output_data(many_data:)
  many_data.each do |ele|
    put ele
  end
end

=> NoMethodError (undefined method `each' for nil:NilClass)

引数のmany_dataにnilが入ってしまう場合です。

この場合の解決方法として、よくありそうなのが

def output_data(many_data:)
  return if many_data.nil?
  many_data.each do |ele|
    put ele
  end
end

の様にして、ガードするというケース。

そして、もう一つ今回紹介したいのがArrayの初期化処理を使う方法です。

具体的には以下。

def output_data(many_data:)
  Array(many_data).each do |ele|
    put ele
  end
end

Arrayに引数を渡すことによって、

irb(main):030:0> Array(nil)
=> []

値がnilの場合でも空の配列を返してくれます!
これは嬉しいですね!

2時次元配列を1次元配列で結合したい

今この場に、過去にいろいろあったらしく、2次元配列に格納されてしまっているデータたちがいます。
この格納されているデータを1次元配列にして、ランダムにデータを取りたい!
と、勇者は思いました。

その第一ステップとして、2次元配列データを1次元配列データに打ち込み直したい。。。

やりたいことは

[['data1_01','data1_02'], ['data2_01'], ['data3_01'], [nil]]

['data1_01','data1_02', 'data2_01', 'data3_01']

こんな感じ。

こんな、デコボコした2次元配列を、平らに、そう、フラットにする便利な方法をないだろうか。。。。

Rubyにはあったあああ

そう!flattenメソッド!

irb(main):034:0> [['data1_01','data1_02'], ['data2_01'], ['data3_01'], [nil]].flatten
=> ["data1_01", "data1_02", "data2_01", "data3_01", nil]

おおお、 あんなデコボコした配列も、平和に平らになりました。

1次配列からnilを抜きたい。

おっと、さっきflattenメソッドで1次配列にしたものの、nilが入ってしまいました。

平和に不協和が。

データはランダムに取りたいものの、nilが取れては意味がないので、nilは抜いておきたいものですようね。

["data1_01", "data1_02", "data2_01", "data3_01", nil]

nilという、使えないデータを取り除き、配列を整理する方法はないだろうか。配列を綺麗に、コンパクトにしたい。。。!

そう、そんな時はcompactメソッド!

irb(main):035:0> ["data1_01", "data1_02", "data2_01", "data3_01", nil].compact
=> ["data1_01", "data1_02", "data2_01", "data3_01"]

配列なんでもいいから適当に値が欲しい!できればランダムで!

さぁ、処置は最終局面まできました。
2次元であった配列も今や、nilすら取り除かれた1次元配列!
ここまでくればデータを取るのも楽勝でしょう。
そんな配列から今回はランダムで、データが取りたい!

["data1_01", "data1_02", "data2_01", "data3_01"]

"data1_01"

["data1_01", "data1_02", "data2_01", "data3_01"]

"data2_01"

乱数(rand関数)を使う?
いや、こんな時もrubyにはとても便利なメソッドがありました

その名もsampleメソッド!!

irb(main):049:0> ["data1_01", "data1_02", "data2_01", "data3_01"].sample
=> "data2_01"
irb(main):050:0> ["data1_01", "data1_02", "data2_01", "data3_01"].sample
=> "data1_02"

以上で紹介を終わります。

参考

How To Use Array Methods in Ruby | DigitalOcean
Class: Array (Ruby 2.2.0)