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

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

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

CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

Ruby

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

ハッシュ

ハッシュは、高速にデータ検索を行うアルゴリズムのことです。

Q&A

解決済

2回答

1543閲覧

【Ruby,CSV】複数のCSVファイルを読み出し、ハッシュに格納する方法

yn047

総合スコア10

CSV

CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

Ruby

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

ハッシュ

ハッシュは、高速にデータ検索を行うアルゴリズムのことです。

0グッド

0クリップ

投稿2020/02/03 06:33

編集2020/02/03 12:07

前提・実現したいこと

この質問は、下記URLにある前回分の質問からの続きになっております。
https://teratail.com/questions/238752

現在、電車の経路案内プログラムを作成しております。
今回は2つCSVファイルから特定のデータを抽出し、ハッシュに格納したいと考えております。
1つ目のCSVから駅のコードを取得し、2つ目のCSVでは1つ目で取得した駅のコードに対応する隣接駅のデータを取得し、
ハッシュ形式で出力したいです。

期待する出力は下記の通りです。
["station1", "station2"]

→例:
[1110101, 1110102]
[1110102, 1110103]
[1110103, 1110104]
[1110104, 1110105]
[1110105, 1110108]
[1110105, 1110106]
[1110106, 1110107]
[1110107, 1110108]

CSVファイルの詳細は下記の通りです。

①station20191227.csv
駅情報に関する情報が格納されたCSVファイル
→1つ目の駅を取得します

※情報量が多いため、全データについては下記URLをご参照ください。
https://drive.google.com/open?id=13tOxt-KrPVVKnM7UCZyle_9KoFBoisLP

CSV

1station_cd,station_g_cd,station_name,station_name_k,station_name_r,line_cd,pref_cd,post,add,lon,lat,open_ymd,close_ymd,e_status,e_sort 21110101,1110101,函館,,,11101,1,040-0063,北海道函館市若松町12-13,140.726413,41.773709,1902-12-10,,0,1110101 31110102,1110102,五稜郭,,,11101,1,041-0813,函館市亀田本町,140.733539,41.803557,,,0,1110102 41110103,1110103,桔梗,,,11101,1,041-0801,北海道函館市桔梗3丁目41-36,140.722952,41.846457,1902-12-10,,0,1110103 51110104,1110104,大中山,,,11101,1,041-1121,亀田郡七飯町大字大中山,140.71358,41.864641,,,0,1110104 61110105,1110105,七飯,,,11101,1,041-1111,亀田郡七飯町字本町,140.688556,41.886971,,,0,1110105 71110106,1110106,新函館北斗,,,11101,1,041-1242,北海道北斗市市渡,140.646525,41.9054,1902-12-10,,0,1110106 81110107,1110107,仁山,,,11101,1,041-1101,亀田郡七飯町字仁山,140.635183,41.930011,,,0,1110107 91110108,1110108,大沼,,,11101,1,041-1354,北海道亀田郡七飯町字大沼町4,140.669347,41.971954,1903-06-28,,0,1110108 101110109,1110109,大沼公園,,,11101,1,041-1354,北海道亀田郡七飯町字大沼町85,140.669758,41.980958,1907-06-05,,0,1110109 111110110,1110110,赤井川,,,11101,1,049-2142,茅部郡森町字赤井川,140.642678,42.003267,,,0,1110110

②join20191227.csv
どの駅とどの駅が隣接しているかを確認するための情報が格納されたCSVファイル
→①で取得した駅と隣接する駅を取得します

※情報量が多いため、全データについては下記URLをご参照ください。
https://drive.google.com/open?id=1CmOfR_j_a7FJ0QgHi568fk7SYMXI67J-

CSV

1line_cd,station_cd1,station_cd2 21002,100201,100202 31002,100202,100203 41002,100203,100204 51002,100204,100205 61002,100205,100206 71002,100206,100207 81002,100207,100208 91002,100208,100209 101002,100209,100210 111002,100210,100211

上記ファイルを踏まえ、①でまずはstationcodeを読み込み、②で①のstationcode(stationcode1)に
対応したstationcode2を参照し、ペア(キー:stationcode(=stationcode1) 、値:stationcode2)に
なるように、コンソール上でハッシュとして出力したいです。

発生している問題・エラーメッセージ

CSVファイルの読み込み、隣接する駅同士のペアリングまで実装しました。
しかし、いざ実行しようとすると構文エラーが発生してしまい、動かすことができません。
→syntax error, unexpected end-of-input, expecting end

該当のソースコード

Ruby

1require "csv" 2 3station_codes = {} 4CSV.foreach("station20191227.csv", headers: true) do |row| 5 station_codes.store(row[0]) 6end 7 8CSV.foreach("join20191227.csv", headers: true) do |row| 9 station1 = row[1] # station1 10 station2 = row[2] # station2 11 12 # station_codesのkeyの中からstation1を探す 13 station_codes.keys.each do |key, value| 14 end 15 # もしstation1がstation_codesのkeyに含まれていたら 16if station1 == key 17 # 見つけたkeyのvalueにstation2を追加する 18value << station2 19 # 含まれていなかったら何もしない 20break 21end

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

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

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

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

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

taichi730

2020/02/03 08:26

stationcode1 とか stationcode2 は CSV 上の station_cd とか station_cd1、station_cd2 の事でしょうか? やりたいこととしては、 * ある駅に隣接する駅の一覧を作りたい * 駅コード (stationcode) は、1つ目のCSVから取得 * 2つ目の CSV ファイルから、隣接する駅の組み合わせを取得 で良いでしょうか? また、駅Aと駅Bが隣接しているとして、2つ目の CSV にはどの様に記録されているのでしょうか? * station_cd1 に駅A、station_cd2 に駅B と station_cd1 に駅B、station_cd2 に駅A の両方の組み合わせが記録されている * 上記のうち、片方のみ
taichi730

2020/02/03 08:29

具体的に、読み込みに躓いているとか、ペアを抽出する方法が探し出せないとか、どういう事でしょうか?
asm

2020/02/03 08:35

データを抜粋する際は対応する部分を抜粋していただかないとちょっと困ります・・・ > 対応したstationcode2を参照し、ペア(キー:stationcode(=stationcode1) 、値:stationcode2)に join20191227.csvと何が違うのでしょうか? よく分からないのでサンプル出力を付けることをお願いしたいです。
taichi730

2020/02/03 08:44 編集

期待する出力の提示もないと、的確な回答ができないです。
yn047

2020/02/03 12:14

情報が不足しており申し訳ございません。 やりたいことに関しては、上記内容で間違いございません。 また、期待する出力については質問内容に追記しました。 対象コードについても一部変更を加えました。 お手数おかけしますが、ご確認のほどよろしくお願いいたします。
taichi730

2020/02/03 12:28

隣接駅のない駅はないと思うので、二つ目のCSVを読むだけで充分なような?
taichi730

2020/02/03 12:33

隣接駅が複数個あることを考慮しても、二つ目のCSVだけで足りそうですね
guest

回答2

0

ベストアンサー

以下のようにしてください。
最後の3行は確認用です。

ruby

1require "csv" 2station_codes = Hash.new 3station_codesjoin = Hash.new 4CSV.foreach("station20191227.csv", headers: true) do |row| 5 station_codes[row[0]] = true 6end 7 8CSV.foreach("join20191227.csv", headers: true) do |row| 9 if station_codes.key?(row[1]) == true 10 station_codesjoin[row[1]] = row[2] 11 end 12end 13 14station_codesjoin.each do |key,value| 15 puts "#{key},#{value}" 16end 17

投稿2020/02/04 02:44

tatsu99

総合スコア5493

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

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

yn047

2020/02/04 03:23

ありがとうございます。当方が期待する挙動を確認できました。 ちなみに、下記コードでも同様の挙動で動かすことは可能でしょうか? ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー require "csv" station_codes = {} CSV.foreach("station20191227.csv", headers: true) do |row| station_codes.store(row[0]) end CSV.foreach("join20191227.csv", headers: true) do |row| station1 = row[1] station2 = row[2] station_codes.keys.each do |key, value| if station1 == key value << station2 end end ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー 動かそうとしても、endの位置が違うようで、下記のようなエラーが発生してしまいます。 unexpected token $end (Using Ruby 2.3 parser; configure using `TargetRubyVersion` parameter, under `AllCops`) (error:Lint/Syntax) 恐れ入りますが、ご確認のほどよろしくお願いいたします。
tatsu99

2020/02/04 04:17

もし、そのようにするなら、いかのようになるでしょう。 ----------------------------------------------- require "csv" station_codes = {} CSV.foreach("station20191227.csv", headers: true) do |row| station_codes.store(row[0],[]) end CSV.foreach("join20191227.csv", headers: true) do |row| station1 = row[1] station2 = row[2] station_codes.each do |key, value| if station1 == key station_codes[key] << station2 end end end station_codes.each do |key,value| puts "#{key},#{value}" end ------------------------------------- 最後の3行は確認用です。 但し、私が提示したソースを実行した場合とでは、出力結果がことなります。 私が提示したソースでは ハッシュのキー:stationコード ハッシュの値:隣接するstationコード ですが、あなたの提示したソースは ハッシュのキー:stationコード ハッシュの値:隣接するstationコードの配列 になります。
taichi730

2020/02/04 04:17

if/do の位置と end の位置を揃えたら、どこが問題か分かるのではないですか?
guest

0

追記依頼した内容で、前提が合っているとして。

ruby

1stattion_codes = {} 2CSV.foreach("station20191227free.csv", headers: true) do |row| 3 station_codes[row[0]] = [] 4end 5 6CSV.foreach("join20191227.csv", headers: true) do |row| 7 station_code = [row[1], row[2]] 8 stattion_codes[station_code[0]] << station_code[1] 9 stattion_codes[station_code[1]] << station_code[0] 10end

投稿2020/02/03 08:34

taichi730

総合スコア318

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

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

yn047

2020/02/04 03:19

ありがとうございます。参考にさせていただきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問