k-tokitoh

2019-09-28

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 点。

[1,2,3].flatten # => [1,2,3]
[1,2,3].flatten! # => nil

配列の生成

特に注意すべきは以下。

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