コンテンツにスキップ

配列の操作

配列の初期化

以下の方法で配列のインスタンスを生成できる。

  • []
  • Array[]
  • Array.new
array = []          # => []
array = [1, 2, 3]   # => [1, 2, 3]

Array[]             # => []
Array[1, 2, 3]      # => [1, 2, 3]

Array.new(3)        # => [nil, nil, nil]

配列の演算

足し算

  • 右の配列の要素を、左の配列の末尾に追加する。
a = [1, 2, 3]
b = [3, 4, 5]
p a + b       # => [1, 2, 3, 3, 4, 5]

a += b
p a           # => [1, 2, 3, 3, 4, 5]

引き算

  • 左の配列の要素から、右の配列の要素を除外する。
  • 右の配列が、左の配列にない要素を持っている場合は無視される。
a = [1, 2, 3, 3]
b = [3, 4, 5]
p a - b       # => [1, 2]

a -= b
p a           # => [1, 2]

掛け算

  • 同じ要素を繰り返した新しい配列を作る。
  • 割り算はできない。
a = [1, 2, 3]
p a * 2       # => [1, 2, 3, 1, 2, 3]

a *= 2
p a           # => [1, 2, 3, 1, 2, 3]

# 以下は不可
b = [3, 4, 5]
p a * b       # => no implicit conversion of Array into Integer (TypeError)

和集合

  • 左右の配列を結合して重複を除外する。((a + b).uniq と同じ)
  • 元の配列に重複する要素があっても除外される。
a = [1, 2, 3]
b = [3, 4, 5]
p a | b       # => [1, 2, 3, 4, 5]

c = [6, 6, 6, 7]
p b | c       # => [3, 4, 5, 6, 7]

積集合

  • 左右の配列の共通する要素のみ取り出して重複を除外する。
  • 元の配列に重複する要素があっても除外される。
a = [1, 2, 3]
b = [3, 4, 5]
p a & b       # => [3]

c = [5, 5, 6]
p b & c       # => [5]

Array#delete_if

  • 1 要素ずつブロックへ渡し、その結果が真の要素を self から削除する。
  • Hash#reject! は別名メソッド
  • ただし、 delete_if は常に self を返すが、reject! は要素が 1 つ以上削除されれば self を、 1 つも削除されなければ nil を返す
a = [0, 1, 2, 3, 4, 5]
a.delete_if{|x| x % 2 == 0}   # => [1, 3, 5]
p a                           # => [1, 3, 5]

a = [0, 1, 2, 3, 4, 5]
a.reject!{|x| x % 2 == 0}     # => [1, 3, 5]
p a                           # => [1, 3, 5]


a = [0, 1, 2, 3, 4, 5]
a.delete_if{|x| x > 5}        # => [0, 1, 2, 3, 4, 5]

a = [0, 1, 2, 3, 4, 5]
a.reject!{|x| x > 5}          # => nil

Array#reject

  • ブロックの結果が偽の要素を集めた新しい配列を返す。
# 偶数を除外する (奇数を集める)
a = [1, 2, 3, 4, 5]
a.reject {|i| i % 2 == 0 }  # => [1, 3, 5]
p a                         # => [1, 2, 3, 4, 5]

Array#delete

  • 引数で渡された値と等しい要素を self から削除する。
a = [1, 2, 3, 2, 1]
a.delete(2)           # => 2
p a                   # => [1, 3, 1]

Enumerable#filter

  • 各要素に対してブロック評価した結果が、真である要素の配列を返す。
  • 以下の別名メソッドがある。
    • Enumerable#find_all
    • Enumerable#select
(1..10).find_all                        # => #<Enumerator: 1..10:find_all>
(1..10).find_all { |i| i % 3 == 0 }     # => [3, 6, 9]

[1,2,3,4,5].select                      # => #<Enumerator: [1, 2, 3, 4, 5]:select>
[1,2,3,4,5].select { |num| num.even? }  # => [2, 4]

Array#collect

  • 各要素に対してブロックを評価した結果配列を返す。
  • Array#map は別名メソッド
p [1, 2, 3].map {|n| n * 3 }        # => [3, 6, 9]
p [1, 2, 3].collect {|n| n * 3 }    # => [3, 6, 9]

Enumerable#detect

  • 各要素に対してブロックを評価した結果が、最初に真になった要素を返す。
  • Enumerable#find は別名メソッド
# 最初の 3 の倍数を探す
p [1, 2, 3, 4, 5].detect {|i| i % 3 == 0 }    # => 3
p [2, 2, 2, 2, 2].detect {|i| i % 3 == 0 }    # => nil

p [1, 2, 3, 4, 5].find {|i| i % 3 == 0 }      # => 3
p [2, 2, 2, 2, 2].find {|i| i % 3 == 0 }      # => nil

Enumerable#inject

  • リストの畳み込み演算。
  • Enumerable#reduce は別名メソッド
# 合計を計算する。
p [2, 3, 4, 5].inject {|result, item| result + item }        #=> 14

# 自乗和を計算する。初期値をセットする必要がある。
p [2, 3, 4, 5].inject(0) {|result, item| result + item**2 }  #=> 54

Enumerable#each_cons

  • 要素を重複ありで n 要素ずつに区切り、ブロックに渡して繰り返す。
(1..10).each_cons(3) {|arr| p arr }
# => [1, 2, 3]
#    [2, 3, 4]
#    [3, 4, 5]
#    [4, 5, 6]
#    [5, 6, 7]
#    [6, 7, 8]
#    [7, 8, 9]
#    [8, 9, 10]

Enumerable#each_slice

  • n 要素ずつブロックに渡して繰り返す。
  • 要素数が n で割り切れないときは、最後の回だけ要素数が減る。
(1..10).each_slice(3) {|arr| p arr }
# => [1, 2, 3]
#    [4, 5, 6]
#    [7, 8, 9]
#    [10]