Arrayのメソッドいろいろ

挙動がちょっとややこしいものや、「どうなんだっけ?」となりがちな点についてまとめてメモ。

Array#product

Array#product(*array) -> array

レシーバの配列と引数の配列から、それぞれの全要素を掛け合わせた一次元配列を返す。

main = [:meat, :fish]
salad = [:ceasar, :cobb]

main.product(salad)
=> [
  [:meat, :ceasar],
  [:meat, :cobb],
  [:fish, :ceasar],
  [:fish, :cobb]
]

引数に複数の配列を渡すこともできる。

drink = [:tea, :coffee]

main.product(salad, drink)
=> [
  [:meat, :ceasar, :tea],
  [:meat, :ceasar, :coffee],
  [:meat, :cobb, :tea],
  [:meat, :cobb, :coffee],
  [:fish, :ceasar, :tea],
  [:fish, :ceasar, :coffee],
  [:fish, :cobb, :tea],
  [:fish, :cobb, :coffee]
]

Array#transpose

Array#transpose -> array

2次元配列をレシーバとして、行列を逆転させた2次元配列を返す。

kana = [
  ['', '', '', '', ''],
  ['', '', '', '', ''],
  ['', '', '', '', ''],
  ['', '', '', '', ''],
  ['', '', '', '', '']
]

kana.transpose
=> [
  ["", "", "", "", ""],
  ["", "", "", "", ""],
  ["", "", "", "", ""],
  ["", "", "", "", ""],
  ["", "", "", "", ""]
]

Array#zip

Array#zip(*array) -> array

レシーバの配列及び引数の配列をインデックスごとに対応付け、配列を返す。

main = [:meat, :fish]
salad = [:ceasar, :cobb]

main.zip(salad)
=> [
  [:meat, :ceasar],
  [:fish, :cobb]
]

Array#productは全ての組み合わせを生成したけど、Array#zipはインデックスが同一の要素を対応付けるだけ。

こちらも複数の配列を引数にとることができる。

なおインデックスはレシーバを基準として、引数の配列が対応する要素を欠く場合はnilによって補う。

main = [:meat, :fish, :pasta]
salad = [:ceasar, :cobb]
drink = [:tea, :coffee, :juice]

main.zip(salad, drink)
=> [
  [:meat, :ceasar, :tea],
  [:fish, :cobb, :coffee],
  [:pasta, nil, :juice]
]

各種演算子

arr1 = [1,2,3]
arr2 = [2,3,4]

Array#+

シンプルに要素を足し合わせる。

arr1 + arr2  # => [1, 2, 3, 2, 3, 4]

Array#-

差集合

arr1 - arr2  # => [1]

Array#&

積集合

arr1 & arr2  # => [2, 3]

Array#|

和集合

arr1 | arr2  # => [1, 2, 3, 4]

Array#[]

ゲッターもセッターも原則として参照エラーを起こさない。

frameworks = ['Rails', 'Sinatra']
frameworks[4]  # => nil
frameworks[-5]  # => nil
frameworks[1..3]  # => ["Sinatra"]
frameworks[4] = 'Cuba'
frameworks  # => ["Rails", "Sinatra", nil, nil, "Cuba"]

唯一indexをマイナスで指定したセッターはIndexErrorを返す。

frameworks[-10] = 'hanami'   # => IndexError

Array#flatten!

Array#flattenとの違いは以下2点。

  • 破壊的メソッド
  • 平坦化が行われない場合はnilを返す <- caution!
[1,2,3].flatten   # => [1,2,3]
[1,2,3].flatten!  # => nil

配列の生成

  • Kernel.#Array(arg)
    • arg.to_aが呼べればその値を、呼べなければargを唯一の要素とする配列を返す。
  • Array#new
    • Array#new(size = 0, obj = nil)
    • Array#new(size = 0) {|index| ... }

特に注意すべきは以下。

a1 = Array.new(3, 'hoge')
a2 = Array.new(3) {'hoge'}

a1.each {|s| p s.object_id }
=> 70167535380400
   70167535380400
   70167535380400
a2.each {|s| p s.object_id }
=> 70167535364000
   70167535363980
   70167535363960