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

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

ただいまの
回答率

90.34%

  • Ruby

    10220questions

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

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

解決済

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 1,077

e38284

score 10

自分で作ったコードではなく作ってもらったコードなのですが、どうしても理解できないところがあります。
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]です。
よろしくお願いします。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+2

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

require "csv"
csv_date1=CSV.read("v_relations.csv")

h_word_origins=Hash.new{|h,k| h[k]=Array.new} # 注:下記参照
h_word_relations=Hash.new
a_word_relations=Array.new

csv_date1.each do |row| 
    h_word_relations[row[0]]=row[1]
    h_word_origins[row[1]] << row[0]
    a_word_relations << row
end


p h_word_origins

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/26 21:36

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

    キャンセル

  • 2017/09/28 06: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>'

    こんな感じになってしまいました。

    キャンセル

  • 2017/09/28 07:12

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

    キャンセル

+1

先に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あたりで次のことを試してみると分かりやすいです。

a = nil #-> nil
a << 1 #エラー
a = Array.new #->[]
a << 1 # a = [1]
または
a = Hash.new #->{}
a[:b] # -> nil
a[:b] << 1 #エラー
a[:b] = Array.new #-> []
a[:b] << 1 #->[1]
a # -> {:b=>[1]}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 90.34%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • Ruby

    10220questions

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