LoginSignup
1
0

More than 5 years have passed since last update.

Ruby技術者認定試験 silver その1(配列)

Posted at

はじめに

備忘録として自分の勉強法をまとめておきます。
また,Ruby技術者認定試験を今後受けようと思っている方のお役に立てれば幸いです。

each

ブロックに繰り返し要素を渡す。

each
# すべての要素の和を求める
numbers = [1, 2, 3, 4, 5]
sum = 0
numbers.each { |n| sum += n }
sum #=> 15

delete_if

指定した条件に一致する要素を削除する。

delete_if
numbers = [1, 2, 3, 4, 5]
numbers.delete_if { |n| n.even? }
numbers #=> [1, 3, 5]

map

ブロックが返す値からなる配列を作成する。

map
# すべて2倍にした配列を返す
numbers = [1, 2, 3, 4, 5]
double_numbers = numbers.map { |n| n * 2 }
double_numbers = [2, 4, 6, 8, 10]

Note:
mapcollectと同義

select

ブロックが真を返す要素からなる配列を作成する。

select
# 奇数を集める
numbers = [1, 2, 3, 4, 5]
odd_numbers = numbers.select { |n| n.odd? }
odd_numbers #=> [1, 3, 5]

Note:
selectfind_allと同義

reject

ブロックが偽を返す要素からなる配列を作成する。

reject
# 2で割れる数を除く
numbers = [1, 2, 3, 4, 5]
odd_numbers = numbers.reject { |n| n % 2 == 0 }
odd_numbers #=> [1, 3, 5]

find

ブロックが真となる最初の要素を返す。

find
# 最初の偶数を探す
numbers = [1, 2, 3, 4, 5]
even_number = numbers.find { |n| n.even? }

even_number #=> 2

Note:
finddetectと同義
finddetectEnumerableモジュールのメソッド

inject

たたみ込み演算をおこなう。

indect
# すべての要素の和を求める
numbers = [1, 2, 3, 4, 5]
sum = numbers.inject(0) { |result, n| result + n }

sum #=> 15

ブロックの第一引き数は、

  • 1回目のみinjectの引き数
  • 2回目以降は前回のブロックの返り値

ブロックの第二引き数は、配列の各要素が順に入る。

上のコードの処理の流れ

  1. result = 0, n = 1 → 0 + 1 = 1
  2. result = 1, n = 2 → 1 + 2 = 3
  3. result = 3, n = 3 → 3 + 3 = 6
  4. result = 6, n = 4 → 7 + 4 = 10
  5. result = 10, n = 5 → 10 + 5 = 15

Note:
injectreduceと同義

簡潔に書く

メソッドにブロックを渡す代わりに、&:メソッド名を引き数として渡す。


numbers = [1, 2, 3, 4, 5]

# これを
odd_numbers = numbers.select { |n| n.odd? }

# こう
odd_numbers = numbers.select(&:odd?)

次の条件を満たす場合に使うことができる。

条件

  • ブロック引数が1つだけ
  • ブロック内で呼び出すメソッドに引数がない
  • ブロック内は、ブロック引数に対してメソッドを1回呼び出す処理のみ

(追記)正確には、、ブロック引き数が2つでも使える場合があります。
以下コメントからの引用

「メソッドにブロックを渡す代わりに、&:メソッド名を引き数として渡す。」についてですが,

a = [1, 2, 3]
a.inject(&:+) # => 6

という例もあります。
inject(&:+) はほぼinject{ |r, x| r.+(x) }です。
つまり,ブロックパラメーターが二つ以上の場合にもこういう記法が使えます。

添字付きの繰り返し

  • each_with_index
  • with_index

each_with_index

ブロックに繰り返し要素と添字を渡す。

each_with_index
# i には 0, 1, 2 がはいる
animals = ["dog", "cat", "mouse"]
animals.each_with_index { |animal, i| puts "#{i + 1}. #{animal}" }

#=>
# 1. dog
# 2. cat
# 3. mouse

with_index

each以外のメソッドに添え字を付ける場合は、各メソッドとwith_indexメソッドを組み合わせる。

map.with_index
# map に添え字を付ける
animals = ["dog", "cat", "mouse"]
animals.map.with_index { |animal, i| "#{i + 1}. #{animal}" }

#=> ["1. dog", "2. cat", "3. mouse"]

添字を0以外から始める

with_indexに引き数を渡す。

with_index(1)
# 添字を 1 から始める
animals = ["dog", "cat", "mouse"]
animals.map.with_index(1) { |animal, i| "#{i}. #{animal}" }

#=> ["1. dog", "2. cat", "3. mouse"]

配列の配列に対する繰り返し

ブロック引き数に配列が渡ってくるときは、ブロック引き数を複数個用意する。

dimensions = [
    # [縦, 横]
    [10, 20],
    [30, 40],
    [50, 60],
]

# それぞれの面積を求める
areas = []

# 改良前
dimentions.each { |dimention| areas << dimention[0] * dimention[1] }
# 改良後
dimentions.each { |length, width| areas << length * width }

areas #=> [200, 1200, 3000]

添字を付ける

with_index + ブロック引き数を()で囲む。

dimensions = [
    # [縦, 横]
    [10, 20],
    [30, 40],
    [50, 60],
]

dimensions.each.with_index do |(length, width), i|
    puts "#{length}, #{width}, #{i}"
end

#=>
# 10, 20, 0
# 30, 40, 1
# 50, 60, 2

push

配列を合体する

push
array = [1, 2, 3]
array.push(10, 100)
p array
[1, 2, 3, 10, 100]
push
arr_1 = [0, 1, 2]
=> [0, 1, 2]
arr_2 = [8, 9, 10]
=> [8, 9, 10]
arr_1.push(arr_2))
=> [0, 1, 2, [8, 9, 10]]

pushは「<<」と同義

a = [1, 2]
=> [1, 2]

b = [3, 4]
=> [3, 4]

a << b
=> [1, 2, [3, 4]]

どちらも重複した配列になる。

concat

配列を合体する

concat
arr_1 = [0, 1, 2]
=> [0, 1, 2]

arr_2 = [8, 9, 10]
=> [8, 9, 10]

 arr_1.concat(arr_2)
=> [1, 2, 3, 8, 9, 10]

+演算子と同義。

a = [1, 2]
=> [1, 2]

b = [3, 4]
=> [3, 4]

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

重複しない。

flatten!

:重複配列をフラットにする
(flattenでも可)
「!」は破壊的メソッドなので使用しないほうがいいかも。

flatten
arr_1 = [0, 1, 2]
=> [0, 1, 2]

arr_2 = [8, 9, 10]
=> [8, 9, 10]

arr_1.push(arr_2))
=> [0, 1, 2, [8, 9, 10]]
# 重複しても、、、

arr_1.flatten!
=> [0, 1, 2, 8, 9, 10]
# 解決!

配列の要素を数指定で取得

sample
arr = [0,1,2,3,4,5,6,7,8,9,10]
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# 「.」が2つのとき、10個の要素
arr[0..9]
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 「.」が2つのとき、10個の要素
arr[1..9]
=> [1, 2, 3, 4, 5, 6, 7, 8, 9]

# 「.」が3つのとき、9個の要素
arr[0...9]
=> [0, 1, 2, 3, 4, 5, 6, 7, 8]

# [0..9]の中からランダムに2つだけ取る
arr[0..9].sample(2)
=> [4, 2]

sample

要素をランダムに取得する

sample
arr = [0,1,2,3,4,5,6,7,8,9,10]
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

arr.sample(4)
=> [0, 8, 1, 4]

shuffle

シャッフルする

arr = [0,1,2,3,4,5,6,7,8,9,10]
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

arr.shuffle
=> [4, 8, 9, 2, 5, 1, 3, 7, 10, 0, 6]

arr.shuffle!
=> [5, 0, 4, 7, 6, 2, 1, 9, 10, 3, 8]

uniq

重複した要素を取り除く

a = [0, 1, 2, 4, 6, 3]
=> [0, 1, 2, 4, 6, 3]

b = [0, 1, 2, 6, 3, 5]
=> [0, 1, 2, 6, 3, 5]

c = ((a.sample(3)) + (b.sample(3)))
=> [6, 2, 1, 2, 5, 6]

# ユニークにする
c = ((a.sample(3)) + (b.sample(3))).shuffle!.uniq
=> [0, 6, 2, 3]

c = ((a.sample(3).uniq) + (b.sample(3)).uniq).shuffle!
=> [3, 1, 1, 2, 0, 4]

c = ((a.sample(3)) + (b.sample(3))).uniq.shuffle!
=> [4, 2, 3, 1, 6]

c = ((a.sample(3)) + (b.sample(3))).uniq.shuffle!
=> [0, 6, 4, 3, 1, 2]

combination

組み合わせ

arr = [1, 2, 3]
=> [1, 2, 3]

arr.combination(2){|x| print x}
[1, 2][1, 3][2, 3]=> [1, 2, 3]

3個の要素から2個を選んだ。
3C2の計算 = 3P2/2! = 3通り

permutation

順列

arr = [1, 2, 3]
=> [1, 2, 3]

arr.permutation(2){|x| print x}
[1, 2][1, 3][2, 1][2, 3][3, 1][3, 2]=> [1, 2, 3]

3P2 = 6通り

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0