7日目(2)：Ruby認定試験による勉強

今日の分は、何をやってるか、まったくわからないものが多かった。
あと、あと範囲オブジェクトと[]あたりがごちゃごちゃのままの様だ。

#演算子のオーバーライド
[参照：Ruby 2.6.0 リファレンスマニュアル > 演算子式](https://docs.ruby-lang.org/ja/latest/doc/spec=2foperator.html)

多くの言語：演算子は、言語の組み込み機能で、通常の関数やメソッドとは別。
Ruby の場合、これらの演算子の多くが、ただのメソッドとして定義。

##再定義できる演算子
```
|  ^  &  <=>  ==  ===  =~  >   >=  <   <=   <<  >>
+  -  *  /    %   **   ~   +@  -@  []  []=  ` ! != !~
```
##再定義不可の演算子
演算子の組合せである自己代入演算子は再定義できない。

```
=  ?:  ..  ...  not  &&  and  ||  or  ::
```
##演算子の定義方法
[引用：Ruby 2.6.0 リファレンスマニュアル > クラス／メソッドの定義；演算子式の定義](https://docs.ruby-lang.org/ja/latest/doc/spec=2fdef.html#operator)
わからない。

```
# 二項演算子
def +(other)                # obj + other
def -(other)                # obj - other

# 単項プラス/マイナス
def +@                      # +obj
def -@                      # -obj

# 要素代入
def foo=(value)             # obj.foo = value

# [] と []=
def [](key)                 # obj[key]
def []=(key, value)         # obj[key] = value
def []=(key, key2, value)   # obj[key, key2] = value

# バッククォート記法
def `(arg)                  # `arg` または %x(arg)
```

#メソッドのオーバーライドと比較演算子
```
##比較演算子と<<　　：問題
class Employee
  attr_reader :id
  attr_accessor :name
  
  def initialize id, name
    @id = id
    @name = name
  end
  
  def to_s
    return "#{@id}:#{@name}"
  end
  #ここに代入する式を選択して下さい。
end

employees = []
employees << Employee.new("3","Tanaka")
employees << Employee.new("1","Suzuki")
employees << Employee.new("2","Sato")
employees.sort!
employees.each do |employee| puts employee end

# 実行結果
1:Suzuki
2:Sato
3:Tanaka

# 選択肢
# 1 (答え）
def <=> other
  return self.id <=> other.id
end
```
##比較演算子<=>

| 1 | 2 |
|:-:|:-:|
| a < b  | -1  |
| a == b  | 0  |
| a > b  | 1  |
| 比較不可  |  nil |

##<<とは(array)
[参考：<< (Array) rubyレファレンス](https://ref.xaio.jp/ruby/classes/array/append)
<<<演算子（メソッド）は、左辺の配列（レシーバ）の末尾に右辺のオブジェクトを要素として加えます。

```
#例
animals = ["dog", "cat", "mouse"]
animals << "pig"
p animals
["dog", "cat", "mouse", "pig"]
```

#&&と&とand、||と|とorの違い
```
#問題
a = [1,2,3,4]
b = [1,3,5,7]
#ここに代入する式を選択して下さい。
c = XXXX
c.each {|i| print i, " " }
#出力結果
1  3
#選択肢
1. a+b ,2. a-b  ,3. a & b  ,4. a && b ,  5. a | b , 6. a || b
#解答　3
```
##解説
&&演算子は左辺の評価結果がfalseの場合は、右辺を評価せずに次の処理に進む
|| 演算子は、左辺の評価結果がtrue の場合は、右辺を評価せずに次の処理に進む
|演算子と&演算子は、左辺の評価結果に関係なく、右辺を評価する

#範囲オブジェクト
```
#範囲オブジェクト等：問題
a = [1,2,3,4]
#ここに代入する式を選択して下さい。
a.each do |i|
  print i, " "
end
#実行結果
1 2 3

# 選択肢
1. a[0..3]  ,2. a[0..-2]  ,3. a[0...-2]  ,4. a[0...-3] ,
5. a[3,0]  , 6. a[0,3]    ,7. a[2,0]       ,8. a[0,2]
# 答えは2と6
```
##範囲オブジェクト
マイナスまで使えるとは
[何度も出てきてるので、端から端まで要参照](https://docs.ruby-lang.org/ja/latest/class/Range.html)

#配列のメソッド：適切なものを選べ
```
#問題選択肢
1. find_allとselectは同じ動作をする。
2. mapとcollectは同じ動作をする。
3. findとselectは同じ動作をする。
4. firstは先頭要素を削除し、その要素を返す。
5. concatは非破壊的メソッドである。
6. concat!は破壊的メソッドである。
#解答
1と2
```
##select と　find_all
同じ動作を、条件に合う配列をそのまま出力

```
#select
[1, 2, 3, 4, 5].select{ |v| v % 2 == 1 }
=> [1, 3, 5]
#find_all
[1, 2, 3, 4, 5].find_all{ |v| v % 2 == 1 }
=> [1, 3, 5]
```
## map と　collect
同じ動作をし、条件にある配列をtrue or falseで出力

```
#map
[1, 2, 3, 4, 5].map{ |v| v % 2 == 1 }
=> [true, false, true, false, true]
#collect
[1, 2, 3, 4, 5].collect{ |v| v % 2 == 1 }
=> [true, false, true, false, true]
```
## find
findは先頭要素だけ出力

```
#find
[1, 2, 3, 4, 5].find{ |v| v % 2 == 1 }
=> 1
```

## 破壊的メソッドconcat
concat!は定義されていない

```
val = [ "a", "b" ]
c=> ["a", "b"]
val.concat( ["c", "d"] ) #=> [ "a", "b", "c", "d" ]
=> ["a", "b", "c", "d"]l
puts val
a
b
c
d
```
最後、valの値が変化している所、、要注意

#zip[array] :コード結果を選べ
```
a1=%w(a b)
a2=%w(x y)
a3=a1.zip(a2)
p a3.first

# 選択肢
1. "a"  ,2. ["a"]    ,3. ["a", "x"]  ,4. ["a", "b"]  ,5. 例外が発生する。
#　解答
```
##%w( )
配列を作る。配列の要素はスペース区切りで指定する。
式の展開はされない。
##zip array
[参考](https://ref.xaio.jp/ruby/classes/array/zip)
>zipメソッドは、配列の要素を引数の配列other_arrayの要素と組み合わせ、配列の配列を作成して返します。行と列を入れ替えるが、足りない要素はnilで埋められ、余分な要素は捨てられます。

```
arr1 = [1, 2, 3]
arr2 = [4, 5]
arr3 = [6, 7, 8, 9]
p arr1.zip(arr2, arr3)
[[1, 4, 6], [2, 5, 7], [3, nil, 8]]
```

#slice() ：実行結果をかけ
```
a = [1,2,3,4,5]
p a.slice(1,3)

#答え
```
##slice()
[要参照](https://ref.xaio.jp/ruby/classes/array/slice)
sliceメソッドは、[]メソッドの別名です。配列から引数で指定した位置の要素を取り出して返す。

#equal：実行結果を書け
```
a = "abc"
b = "abc"
print a.eql? b
print a.equal? b
print a == b

#　答え
true  false  true
```
##eql?
ハッシュの内部で「同じキーかどうか」を調べるために使われるメソッド.
今回は、レシーバabcが引数abcと同じかどうか調べている
##eqal?(object)
レシーバobjと引数other_objが同じオブジェクトならtrue、別のオブジェクトならfalseを返す。
objent絡みなので、変数名が違うと、falseを返すのだろう。。。？

#型の取り扱い：エラーにならないものを選べ
```
1. puts 5 + "Hello"     ,2. puts "Hello" + 5
3. puts "Hello" * 5     ,4. puts 5 * "Hello"

# 答え
```
##integerとstring
勘違いしていた
例えば、`puts hoge + "ほげ"`であっても、hogeが整数型の変数なら、hogeほげと返す

#concatとchopとchomp：実行結果を書け
```
s1 = "Hoge"
s2 = "Fuga"
s1.concat(s2)
s1.chop
s1.chomp
s1 + s2
puts s1

# 答え
```
##concat
破壊的メソッド。<< や　pushに似ている
##chop
文字列の末尾から1文字を取り除いた新しい文字列を返す。
"\r\n"で終わっている場合だけは、"\r\n"の2文字を取り除きます。
##chomp
文字列の末尾の改行文字を取り除いた新しい文字列を返す。
改行文字は"\n"、"\r\n"、"\r"のどれでも取り除きます
###今回の流れ
```
# irb
s1 = "Hoge"
s2 = "Fuga"

s1.concat(s2)
.c=> "HogeFuga"
# chopでs1末尾のeが取り除かれる
s1.chop
=> "HogeFug"
# s1に改行文字は含まれていない
s1.chomp  
=> "HogeFuga"
# 文字型同士の和は可能
s1 + s2
=> "HogeFugaFuga"
# concatの破壊的性質により、s1.concat(s2)の時点で、s1がHogeFugaに。
puts s1
HogeFuga
```

#[]メソッド　:実行結果を書け
```
s = "123456789"
p s[1,4]

#　解答
"2345"
```
##解説
まず、範囲オブジェクトの類だと思っていた。
[要参照：[] (Array)](https://ref.xaio.jp/ruby/classes/array/element_ref)
slice()の別名

#Hashクラス　:　適切なものを選べ2つ
```
#選択肢
1, {}で空のHashオブジェクトを生成できる。
2, []で空のHashオブジェクトを生成できる。
3, invertでキーと値を入れ替えることができる。
4, keyに対応する値を取り出すメソッドとして、has_key?(key)、key?(key)、get_ key(key)などが用意されている。
5, すべての要素を削除するには、delete_allを使用する。

#答え
３と、２(答えを忘れた。後でまた調べる
```
##Hashクラス
ハッシュオブジェクトの元になっているクラス
##[]
[]メソッドは、配列から引数で指定した位置の要素を取り出して返します。引数には、整数（位置）、整数2つ（位置と数）、範囲を指定できます。
##{}
Hash作成
##invert
キーを値に、値をキーにしたハッシュを作成
##key
has_key?メソッドは、ハッシュが引数keyと同じキーを持っていればtrue、なければfalseを返します。
key?メソッド、include?, member?メソッドは、has_key?の別名
##delete_all
検索でdelete hashはヒットするが、delete_all hash はヒットしない

#Hashクラス: 適切でないものを選べ
```
#選択肢
1, deleteはキーを指定してキーと値の組を削除する。
2, removeはキーと値の組を削除する。
3, fetchは与えられたキーに関連付けられた値を返す。
4, clearはハッシュの要素を全て削除する。

#答え　　１と４
```
## delete
ハッシュから引数keyと同じキーを探して、キーと値を削除。レシーバ自身を変更するメソッドです。
## remove
検索でヒットしない。定義されてないかな。
## fetch
ハッシュから引数で指定したキーの値を取り出して返します。[]メソッドと機能は同じ.
だが、キーが存在しないときの動作が異なる
## clear
キーと値をすべて削除し、ハッシュを空にします。レシーバ自身を変更するメソッドです。

#Hashクラス：実行結果をかけ
```
#{} の問題
v = {}
v.class
#出力答え　Hash
```

#Hashクラス：実行結果をかけ
```
#invert array : 問題
v = {:v1 => 1, :v2 => v}
v.invert
#出力答え　{1=>:v1, nil=>:v2}
```
##invertメソッド
既に上で記述済み

#%等々：回答を選択しから選べ
```
member = [10, "Tanaka"]
print "ID:%2d Name:%s" #ここに代入する式を選択して下さい。  
member
# 実行結果
ID:10 Name:Tanaka
# 選択肢
1. ,   ,2. +
3. %    ,4. .format

#答え　%
```

##%dと%s,%
###%dとは
数字を文字列にしている

```
#irb
sprintf("%d", 4);
=> "4"

# %2d 2桁の文字列を返す
sprintf("%2d", 4);
=> " 4"

# %02d 2桁の文字列を返す。桁数が足りない場合は、前に0を追加。
sprintf("%02d", 4);
=> "04"
```
### % の役割
うまいこと、検索でヒットさせれない
が、実行結果からして、シングルクオートやダブルクオートのエスケープが不要になる。

### %s
シンボル:を付ける。式の展開はされない。

#Hashクラス：適切な選択肢を
```
#配列、シンボル　問題
h = #ここに代入する式を選択して下さい。
p h
#選択肢
1. {a:1,b:2,c:3}　　　、2. {a=1,b=2,c=3}
3. Hash[:a, 1, :b, 2, :c, 3]　　　　、4. {:a1,:b2,:c3}
#実行結果
{ :a => 1, :b => 2, :c => 3 }

#答え　４
```
解説必要なし