質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Q&A

解決済

3回答

2093閲覧

Ruby初心者です。コードの内容がわかりません。

e38284

総合スコア12

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

0グッド

0クリップ

投稿2016/03/07 09:01

自分で作ったコードではなく作ってもらったコードなのですが、どうしても理解できないところがあります。
8行目のunlessを用いて条件式を表しているのはわかるのですが、偽のときに〜Array.newとするのところがわかりません。
なぜこのような表記にするのでしょうか?
また、10行目の h_word_origins[row[1]] << row[0]もわかりません。
わからないことばかりで、恥ずかしいのですがご鞭撻のほどよろしくお願いします。

require "csv" csv_date1=CSV.read("v_relations.csv") h_word_origins=Hash.new h_word_relations=Hash.new a_word_relations=Array.new csv_date1.each do |row| h_word_relations[row[0]]=row[1] unless h_word_origins[row[1]] then h_word_origins[row[1]]=Array.new end h_word_origins[row[1]] << row[0] a_word_relations << row end p h_word_origins
"ssDNA"=>["パルボウイルス科", "サーコウイルス科"], "dsDNA(RT)"=>["ヘパドナウイルス科"], "dsDNA"=>["ポックスウイルス科", "パピローマウイルス科", "アスファーウイルス科", "イリドウイルス科", "ポリオーマウイルス科", "ヘルペスウイルス科", "アデノウイルス科"]

"ssDNA"がrow[1]で、"パルボウイルス科"がrow[0]です。
よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

このような処理は普通はこう書きます。

Ruby

1require "csv" 2csv_date1=CSV.read("v_relations.csv") 3 4h_word_origins=Hash.new{|h,k| h[k]=Array.new} # 注:下記参照 5h_word_relations=Hash.new 6a_word_relations=Array.new 7 8csv_date1.each do |row| 9 h_word_relations[row[0]]=row[1] 10 h_word_origins[row[1]] << row[0] 11 a_word_relations << row 12end 13 14 15p h_word_origins

注を付けたのは「h_word_origins に未定義のキーを指定して値を参照した場合に、Array.newを返すようなHash」という意味です。
これは、h_word_origins の初出のキーの時に、値が空のArrayになって欲しいからです。

これをしないで、単にHash.newとしているので、初出のキーの時には値はnilになってしまいます。しょうがないのでunlessでそれ(nil)を見つけてArray.newにするという、まどろっこしいことをしているわけです。

投稿2016/03/07 14:08

otn

総合スコア84499

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kintarock777

2017/09/25 13:58 編集

csv関連のtopicsを読んでいて、写経してみたのですが、 csvファイルをうまく開けません c:\Ruby23-x64\ruby>ruby csv02.rb C:/Ruby23-x64/lib/ruby/2.3.0/csv.rb:2016:in `=~': invalid byte sequence in Windows-31J (ArgumentError) from C:/Ruby23-x64/lib/ruby/2.3.0/csv.rb:2016:in `init_separators' from C:/Ruby23-x64/lib/ruby/2.3.0/csv.rb:1538:in `initialize' from C:/Ruby23-x64/lib/ruby/2.3.0/csv.rb:1273:in `new' from C:/Ruby23-x64/lib/ruby/2.3.0/csv.rb:1273:in `open' from C:/Ruby23-x64/lib/ruby/2.3.0/csv.rb:1339:in `read' from csv02.rb:2:in `<main>' このように出てしまうのですが、何がいけないのでしょうか? otnさんのコードを丸写ししてみたのですが
otn

2017/09/25 16:13

> invalid byte sequence in Windows-31J 文字コードのエラーですね。データがWindows-31Jでない。
kintarock777

2017/09/26 11:19

回答ありがとうございます。 実際にcsvファイルを読み込むには、どうすればよいのでしょうか?
otn

2017/09/26 12:36

ファイルの文字コードをシフトJISに変換してから読み込んでください。
kintarock777

2017/09/27 21:34

文字コードを S JIS に変換してから読み込んでみました。 今度は ruby 2.3.3p222 (2016-11-21 revision 56859) [x64-mingw32] C:\Users\owner>cd c:\ruby23-x64\ruby c:\Ruby23-x64\ruby>ruby test04.rb C:/Ruby23-x64/lib/ruby/2.3.0/csv.rb:1872:in `block (2 levels) in shift': Missing or stray quote in line 1 (CSV::MalformedCSVError) from C:/Ruby23-x64/lib/ruby/2.3.0/csv.rb:1845:in `each' from C:/Ruby23-x64/lib/ruby/2.3.0/csv.rb:1845:in `block in shift' from C:/Ruby23-x64/lib/ruby/2.3.0/csv.rb:1805:in `loop' from C:/Ruby23-x64/lib/ruby/2.3.0/csv.rb:1805:in `shift' from C:/Ruby23-x64/lib/ruby/2.3.0/csv.rb:1747:in `each' from C:/Ruby23-x64/lib/ruby/2.3.0/csv.rb:1761:in `to_a' from C:/Ruby23-x64/lib/ruby/2.3.0/csv.rb:1761:in `read' from C:/Ruby23-x64/lib/ruby/2.3.0/csv.rb:1339:in `block in read' from C:/Ruby23-x64/lib/ruby/2.3.0/csv.rb:1282:in `open' from C:/Ruby23-x64/lib/ruby/2.3.0/csv.rb:1339:in `read' from test04.rb:2:in `<main>' こんな感じになってしまいました。
otn

2017/09/27 22:12

データが不正なCSV形式ですね。正しいCSV形式に直してください。
guest

0

先に10行目の h_word_origins[row[1]] << row[0]を理解すると,unlessの部分がわかりやすくなります。

まず<<は配列の末尾に項目を追加する演算子です。すなわちハッシュh_word_originsのキーがrow[1]の値として,row[0]を追加するという式が10行目の意味になります。

とすれば裏を返すと,h_word_originsのキーrow[1]の値は配列(少なくとも空の)でなければなりません。

そこで8行目のunless部分が必要になっています。irbあたりで次のことを試してみると分かりやすいです。

ruby

1a = nil #-> nil 2a << 1 #エラー 3a = Array.new #->[] 4a << 1 # a = [1] 5または 6a = Hash.new #->{} 7a[:b] # -> nil 8a[:b] << 1 #エラー 9a[:b] = Array.new #-> [] 10a[:b] << 1 #->[1] 11a # -> {:b=>[1]}

投稿2016/03/07 10:03

NCC1701

総合スコア1680

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

外してやってみたらわかると思うのですが、キーが定義されていないから配列で初期化していますね。

投稿2016/03/07 09:06

fagai

総合スコア2158

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問