[Ruby] hash の配列を、その1要素を key にした hash にする

```ruby
[
  {id: 1, name: 'aaa', user_uuid: 'b43f670d-a367-8eed-e0b4-0c561b0b0d51'},
  {id: 2, name: 'bbb', user_uuid: '4070ec80-9c88-5a64-ca01-2fb25cb6c45e'},
  {id: 3, name: 'ccc', user_uuid: 'b59345bd-3cda-89cc-e1a0-793c740e1442'},
]
```
これを
```ruby
{
  'b43f670d-a367-8eed-e0b4-0c561b0b0d51' => {id: 1, name: 'aaa', user_uuid: 'b43f670d-a367-8eed-e0b4-0c561b0b0d51'},
  '4070ec80-9c88-5a64-ca01-2fb25cb6c45e' => {id: 2, name: 'bbb', user_uuid: '4070ec80-9c88-5a64-ca01-2fb25cb6c45e'},
  'b59345bd-3cda-89cc-e1a0-793c740e1442' => {id: 3, name: 'ccc', user_uuid: 'b59345bd-3cda-89cc-e1a0-793c740e1442'},
}
```
こうします。

# はじめに
「こっちのダッシュボードとこっちのシステムから出した CSV がそれぞれあって、user_uuid ってのでくっつくようになってるから統合して？」
という時の利用を考えています。
行の1要素のままでは使いにくいので引き出してしまおうという事ですね。

```ruby
require 'csv'

csv_table = CSV.read('sample.csv', encoding: 'BOM|UTF-8', col_sep: ',', row_sep: "\n", headers: true)

csv_table.each do |row|
  p row
end
#<CSV::Row "id":"1" " name":" aaa" " user_uuid":" b43f670d-a367-8eed-e0b4-0c561b0b0d51">
#<CSV::Row "id":"2" " name":" bbb" " user_uuid":" 4070ec80-9c88-5a64-ca01-2fb25cb6c45e">
#<CSV::Row "id":"3" " name":" ccc" " user_uuid":" b59345bd-3cda-89cc-e1a0-793c740e1442">
```
というわけで実際は CSV::Row を想定していますが大きな違いはありません。
sample.csv の中身は冒頭の配列が出てくるような内容です。
```csv
id,name,user_uuid
1,aaa,b43f670d-a367-8eed-e0b4-0c561b0b0d51
2,bbb,4070ec80-9c88-5a64-ca01-2fb25cb6c45e
3,ccc,b59345bd-3cda-89cc-e1a0-793c740e1442
```
どうせ便利な使いきりタイプのコードなので何も考えず each で回して用意した空ハッシュに放り込めば終わりですが、こういう自由な時にいろいろ試しておかないと開発してるときには付け焼刃では太刀打ちできないのです。

```ruby
# 適当な形
require 'csv'

csv_table = CSV.read('sample.csv', encoding: 'BOM|UTF-8', col_sep: ',', row_sep: "\n", headers: true)

hash = {}

csv_table.each do |row|
  hash[row['user_uuid']] = row
end

p hash
# {
#   "b43f670d-a367-8eed-e0b4-0c561b0b0d51"=>#<CSV::Row "id":"1" "name":"aaa" "user_uuid":"b43f670d-a367-8eed-e0b4-0c561b0b0d51">,
#   "4070ec80-9c88-5a64-ca01-2fb25cb6c45e"=>#<CSV::Row "id":"2" "name":"bbb" "user_uuid":"4070ec80-9c88-5a64-ca01-2fb25cb6c45e">,
#   "b59345bd-3cda-89cc-e1a0-793c740e1442"=>#<CSV::Row "id":"3" "name":"ccc" "user_uuid":"b59345bd-3cda-89cc-e1a0-793c740e1442">
# }
```

# 実際のコード

```ruby
require 'csv'

csv_table = CSV.read('sample.csv', encoding: 'BOM|UTF-8', col_sep: ',', row_sep: "\n", headers: true)

hash = csv_table.map{|row|row['user_uuid']}.zip(csv_table).to_h

p hash

# {
#   "b43f670d-a367-8eed-e0b4-0c561b0b0d51"=>#<CSV::Row "id":"1" "name":"aaa" "user_uuid":"b43f670d-a367-8eed-e0b4-0c561b0b0d51">,
#   "4070ec80-9c88-5a64-ca01-2fb25cb6c45e"=>#<CSV::Row "id":"2" "name":"bbb" "user_uuid":"4070ec80-9c88-5a64-ca01-2fb25cb6c45e">,
#   "b59345bd-3cda-89cc-e1a0-793c740e1442"=>#<CSV::Row "id":"3" "name":"ccc" "user_uuid":"b59345bd-3cda-89cc-e1a0-793c740e1442">
# }
```
メソッドチェーンで呼び出せて気分がいいですね。
せっかくなのでそれぞれ順にみてみます。

## map()
```ruby
require 'csv'

csv_table = CSV.read('sample.csv', encoding: 'BOM|UTF-8', col_sep: ',', row_sep: "\n", headers: true)

p csv_table.map{|row|row['user_uuid']}

# ["b43f670d-a367-8eed-e0b4-0c561b0b0d51", "4070ec80-9c88-5a64-ca01-2fb25cb6c45e", "b59345bd-3cda-89cc-e1a0-793c740e1442"]
```

目的の値だけの配列を作成します。

## zip()
```ruby
require 'csv'

csv_table = CSV.read('sample.csv', encoding: 'BOM|UTF-8', col_sep: ',', row_sep: "\n", headers: true)

p csv_table.map{|row|row['user_uuid']}.zip(csv_table)

# [
#   ["b43f670d-a367-8eed-e0b4-0c561b0b0d51", #<CSV::Row "id":"1" "name":"aaa" "user_uuid":"b43f670d-a367-8eed-e0b4-0c561b0b0d51">],
#   ["4070ec80-9c88-5a64-ca01-2fb25cb6c45e", #<CSV::Row "id":"2" "name":"bbb" "user_uuid":"4070ec80-9c88-5a64-ca01-2fb25cb6c45e">],
#   ["b59345bd-3cda-89cc-e1a0-793c740e1442", #<CSV::Row "id":"3" "name":"ccc" "user_uuid":"b59345bd-3cda-89cc-e1a0-793c740e1442">]
# ]
```

目的の値と、その値のもとになった行の配列を作成します。

## to_h()
```ruby
require 'csv'

csv_table = CSV.read('sample.csv', encoding: 'BOM|UTF-8', col_sep: ',', row_sep: "\n", headers: true)

p csv_table.map{|row|row['user_uuid']}.zip(csv_table).to_h

# {
#   "b43f670d-a367-8eed-e0b4-0c561b0b0d51"=>#<CSV::Row "id":"1" "name":"aaa" "user_uuid":"b43f670d-a367-8eed-e0b4-0c561b0b0d51">,
#   "4070ec80-9c88-5a64-ca01-2fb25cb6c45e"=>#<CSV::Row "id":"2" "name":"bbb" "user_uuid":"4070ec80-9c88-5a64-ca01-2fb25cb6c45e">,
#   "b59345bd-3cda-89cc-e1a0-793c740e1442"=>#<CSV::Row "id":"3" "name":"ccc" "user_uuid":"b59345bd-3cda-89cc-e1a0-793c740e1442">
# }
```
最後にそれぞれを [key, value] として hash に変換します。

## おわり
CSV をその内の1要素を key にした hash へ変換できました。
記事の途中で相手が配列から CSV になりましたが基本的に配列でも同じ方法を使えます。

これで受け取ったもう1つの CSV にも user_uuid が共有されていればそこで合流させていけるわけですね。
今回は私がよく使う方法を記載しましたが、もちろん他にもいろいろな手法が取れます。

~~RDB に取り込んだ方が早いのでは？~~