Ruby技術者認定試験 3.1 Silver受験した

試験のrubyバージョンが2020年10月から2から3に変わったのですが、 　
対策本が出ていなかったり、ネットの情報がないため受験するか迷っていました。
ただ、再受験無料キャンペーンがあるっぽいので、落ちた時のショックも少ないかなと思い受験しました。

結果としては、version2の問題などで学習しても問題なかったです。
学習の際、整理した内容を記載します。

## 使用した問題集
- [公式問題集 Ver3.0](https://github.com/ruby-association/prep-test/blob/version3/silver_ja.md)　[（解答）](https://github.com/ruby-association/prep-test/blob/version3/silver_answers_ja.md)
- [公式問題集 Ver2.0](https://gist.github.com/sean2121/945035ef2341f0c39bf40762cd8531e0)　[（解答）]()
- [ミニツク](http://www.minituku.net/courses/1049510743/contents/775230600.html)
- [Rex](https://rex.libertyfish.co.jp/)
- Ruby技術者認定試験合格教本　基本問題
- Ruby技術者認定試験合格教本　演習問題

## SilverにおいてのRuby2 3違い
GitHubの問題集を解くにあたり、ver2と3の違いは以下ぐらいしかない気がします。
### hashの定義方法
```ruby
# キーが文字列は2だとエラーになる
h = {"a": 1, :"b" => 2} 
```

### &. ぼっち演算子
レシーバがnilの場合、nilを返す

```ruby
# キーが文字列は2だとエラーになる
h = {"a": 1, :"b" => 2} 
```


## Enumerableメソッド一覧
### find detect
ブロックに与えられた真の最初の値を返す
```ruby
ary = [ 1, 2, 3, 4, 5 ]
p ary.find{|i| i.odd?}  =>[1]
``` 

### find_all, select, filter
各要素に対してブロックを評価した値が真であった要素を全て含む配列を返す。
ひとつも真がない場合は空の配列を返す。

```ruby
[1,2,3].find_all{|i| i<3} => [1,2]
```
### map collect 
各要素に対してブロックを評価した結果をすべて含む配列を返す
``` ruby
[1,2,3].map{|i| i * 3} => [3,6,9]
```

### filter_map
mapとfilterを同時実行できる
```ruby
[1,2,3].filter_map{|i| i * 3 if i == 1} 
=> [3]
# これがmapだと・・
=> [3, nil, nil]を返す
```

### each_slice(n)
引数に指定したn個ずつブロックに渡す
```ruby
(1..10).each_slice(3) {|a| p a}
    # => [1, 2, 3]
    #    [4, 5, 6]
    #    [7, 8, 9]
    #    [10]
```
## Numericメソッド一覧
### n.step(limit, step)
selfからlimitまで、stepずつ実行する
```ruby
1.step(5,2){|i| p i}
=> 1 3 5
```

## Integerメソッド一覧
###times
指定された値の-1までブロックを繰り返す
```ruby
5.times{|i|
 p i
}
=> 0 1 2 3 4
```

## Stringメソッド一覧
### chop chop!
最後の文字を取り除く、
終端が"\r\n"であればその２文字を取り除く
※改行コード以外も対象

### chomp chomp!
改行コードを取り除く
※改行コードのみ！

### strip strip!
先頭と末尾の空白文字(\t\r\n\f\v)

```ruby
hoge = "hoge hoge \t\r\n\f\v"
hoge.strip
=> "hoge hoge "
```

### sub sub!
正規表現のpatternにマッチした最初の部分を文字列 replaceで置き換えた文字列を生成して返します。
※非破壊的

```ruby
puts "blah blah blah".sub(/blah/, "yay")　=> yay blah blah
```

### gsub gsub!
パターンにマッチした文字列をすべて置き換える
```ruby
puts "blah blah blah".sub(/blah/, "yay") => yay yay yay
```

### replace
引数に指定した文字列に置き換える
※破壊的
```ruby
puts "blah blah blah".replace("yay") => yay
```
### delete delete!
※非破壊的
パターンにマッチした文字列を削除する
```ruby
"abcdefg".delete(a-c) => defg
```

### delete_prefix delete_prefix!
先頭から引数に指定した文字列を削除
```ruby
"abcdef".delete_prefix("ab") => cdef
"abcdef".delete_prefix("bd") => abcdef
```

### delete_suffix delete_suffix!
末尾から引数に指定した文字列を削除
```ruby
"abcdef".delete_suffix("ef") => abcd
"abcdef".delete_suffix("cd") => abcdef
```

### chunk
要素を順番にブロック評価して、その結果によって要素をチャンクに分けた（グループ化した）要素を持つ Enumerator を返します。
``` ruby
[3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5].chunk {|n|
  n.even?
}.each {|even, ary|
  p [even, ary]
}
=> [false, [3, 1]]
   [true, [4]]
   [false, [1, 5, 9]]
   [true, [2, 6]]
   [false, [5, 3, 5]]
```

### match
正規表現にマッチした文字列のmatchDataを返す
```ruby
"abcdefg".match(/[a-c]/) => #<MatchData "a">
```

### slice
引数に指定した文字列を取り出す 
[]と同じ
※非破壊的
```ruby
"ruby".slice(0,3) => ruby
"ruby".slice(/r*/) => r
```

### slice!
sliceの破壊的メソッド
取り出された文字列はオブジェクトから削除される。
```ruby
word = "ruby"
word.slice!(0,2) => "ru"

p word => by
```

### oct
文字列を 8 進文字列であると解釈して、整数に変換します。
```ruby
p "10".oct  # => 8
p "010".oct # => 8
p "8".oct   # => 0
```

### split
引数に一致した文字列を区切りに配列を作成する

```ruby
p "a,b,c,d,e".split(/,/, 1)  # => ["a,b,c,d,e"]
p "a,b,c,d,e".split(/,/, 2)  # => ["a", "b,c,d,e"]
```
### lines (see_also: each_line)
各行の配列を返す
```ruby
"aa\nbb\ncc\n".lines 
=> ["aa\n", "bb\n", "cc\n"]
```

## Arrayメソッド一覧
## *String
*Stringで配列が作成される
※変数に格納する必要あり
``` ruby
hoge = *"a" => ["a"]
hoge = *"a","b" => ["a", "b"]
```

### concat
配列otherと自信の末尾に破壊的に連結
*※破壊的*
```ruby
a = [1,2,3]
b = [4,5,6]
a.concat(b) => [1, 2, 3, 4, 5, 6]
p a =>[1, 2, 3, 4, 5, 6]
```


### reject(reject!)
ブロックに与えられた真を返すもののみ返す
```ruby.rb
a = [120, 40, 20, 80, 160, 60, 180]
reject {|i| i < 80}
=>[120, 80, 160, 180]
``` 

### inject
畳み込み計算を行う
```ruby
[1,2,3].inject(:+) => 6
```

### product
レシーバーと各引数を組み合わせた配列を作成する
```ruby
[1,2].product([3,4])
=> [[1, 3], [1, 4], [2, 3], [2, 4]]
```

## Hashメソッド一覧
### はじめに
#### Hash定義方法
``` ruby
Hash[a: 1, b: 2] => {:a => 1, :b => 2}
Hash[1,1] => {:1 ==> 1}
Hash[1,1,1] => odd number of arguments for Hash (ArgumentError)
{a:1, b:2} => {a:1, b:2}
{:a => 1}
{"a": 1}
{:"a" => 1}
```

#### 空配列の作成
```ruby
Hash([])
Hash[]
Hash.new
{}
```

### has_key? include? key? member?
ハッシュのキーが存在するか
```ruby.rb
h = {a: 2, b: 4, c: 6, d: 8, e: 10}
p h.has_key?(:c)
=> true
```

### invert
値をキーを入れ替える
```ruby
{a: 1, b: 2}.invert => {1=>:a, 2=>:b}
# 重複は後に定義したものに置き換え
{a: 100, b: 100}.invert => {100=>:b}
```

### delete
※破壊的
キーに対応する要素を削除する
``` ruby
hash = {a:1 , b:2}
hash.delete(:a)
p hash => {:b=>2}   
```

### fetch
キーに対応する要素を返す
``` ruby
hash = {a:1 , b:2}
hash.fetch(:a) => 1
```

### clear
ハッシュ内をすべて削除
※破壊的
```ruby
hash = {a: 1, b: 2}
hash.clear
p hash => {}
```

### merge merge!(update)
ハッシュを統合する
```ruby
a = {a: 100, b: 200}
b = {b: 200, c: 300}
a.merge(b) => {a: 100 b: 200, c: 300}
```

## 他
### ローカル変数、インスタンス変数、クラス変数
- ローカル変数 _または小文字で始まる文字列
- インスタンス変数 @で始める
- クラス変数 @@で始める
- グローバル変数 $で始める

なお、グローバル変数、インスタンス変数の場合、以下の省略記法が使える
``` ruby
$a = "hoge"
@b = "hige"

p "fuga #$a #@b"
=> fuga hoge hige
```

### 配列で演算子を使用
```ruby.rb
p ["apple", "banana"] & ["banana", "carrot"]
=> ["banana"]

p ["apple", "banana"] | ["banana", "carrot"]
=> ["apple", "banana", "carrot"]

p %i(x1 x2 x3)
=> [:x1, :x2, :x3]
```

### 10進数以外の整数リテラル
- 2進数の場合、2b
- 8進数の場合、0
- 16進数の場合、0x

### オーバーライドできない演算子
``` ruby
= ?: .. ... not && and || or ::
```

### 特殊な出力
[文字列パターン % 配列]で配列の要素を文字列に埋め込み出力する
```
member = [10, "Tanaka"]
print "ID:%2d Name:%s" % member
=> ID:10 Name:Tanaka
```

### strftimeの指定文字
| 指定文字 | 動作         | 
| -------- | ------------ | 
| %Y       | ４桁の西暦   | 
| %y       | 下２桁の西暦 | 
| %m       | 月           | 
| %d       | 日           | 
| %H       | 時刻         | 
| %M       | 分           | 
| %S       | 秒           | 

### 正規表現の紛らわしいところ
| 正規表現 | 説明            | 
| -------- | --------------- | 
| .        | 任意の１文字    | 
| a?       | 0または１文字   | 
| a*       | 0またはそれ以上 | 
| a+       | 1文字以上       | 

### == eql? equal?のち外
- ==　値が同じであればtrue。1 == 1.0もtrueになる。
- eql?　値とクラスが同じであればtrue。1.eql?(1.0)はfalseになる。
- equal?　object_idが同じであればtrue。
``` ruby
x = 1
y = 1.0
x == 1 => true
x.eql?(y) => false
x.equal?(y) => false
x.equal?(1) => true # 1はどこで参照しても同じオブジェクトIDなので、trueになる。

```

### !が付かない破壊的メソッド
- Array#concat
- Array#pop
- Array#push
- Array#shift
- Array#unshift
- Array#delete
- Array#clear
- String#concat
- Hash#update
- Hash#delete　※String#deleteは非破壊的
- Hash#delete_if
- Hash#clear
- Hash#invert

### r r+ w w+ a a+
+がつくと、読み書き両方が付く
- r+は、ファイルを読み込んで、書き込みたいとき
- w+は、データを空にして書き込みたいとき
- a+は、追記モード。既存のデータは変更できない。

### メモ
- 特異メソッドは、後に定義したメソッドよりも特異メソッドが優先される
- PIはモジュールなので、include Mathするか、Math::PIする
- +演算子は非破壊メソッド
- IO#seek seek(offset, IO::SEEK_END)
- IO::SEEK_SET: ファイルの先頭から (デフォルト),IO::SEEK_END: ファイルの末尾から
- String#ord 文字列の文字コードを返す "a".ord => 97
- オブジェクトIDが変わるタイミングは、再代入されたとき。破壊的に変更した時は、変更されない。

### 参考記事

https://qiita.com/Yukidaruma1597/items/c877ba6c54c42b839aa2

https://qiita.com/universato/items/a2a75e0ef120604ec3e5#%E5%AE%9F%E9%9A%9B%E3%81%AB%E5%87%BA%E9%A1%8C%E3%81%95%E3%82%8C%E3%81%9F%E5%86%85%E5%AE%B9

https://qiita.com/motty93/items/413485469e4ec665c329

https://qiita.com/menmenshod/items/aa03c7fe1701a1f03a56