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

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

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

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

Ruby

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

Q&A

解決済

2回答

893閲覧

Ruby CSVファイル読み込み後のデータ検索に時間がかかる

退会済みユーザー

退会済みユーザー

総合スコア0

CSV

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

Ruby

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

0グッド

0クリップ

投稿2018/07/16 14:37

前提・実現したいこと

CSVファイルの読み込み後の処理を早くしたいです。

保存してあるCSVファイル(ファイル名:kudamono.csv)

no, date, kakaku, name
1, 20190101, 300yen, ichigo,
2, 20190102, 310yen, mikan,
3, 20190102, 315yen, budou,
4, 20190102, 310yen, ringo,
5, 20190103, 308yen, suika,


50000, 20191230, 304yen, orenge

といった50000行のcsvのファイルの、
2列目のdateにある特定の日付が入っている行のみを出力したいと考えています。

*例えば、20190102のデータが欲しい時には次の3つが表示されるようにする。
2, 20190102, 310yen, mikan,
3, 20190102, 315yen, budou,
4, 20190102, 310yen, ringo,

いまのコードでは時間がかかってしまうので、何か良い方法はないでしょうか?
実際にはこれら作業を2列目の日付を変え繰り返し行うので、いまのコードだと非常に遅いです。皆様の知恵を貸して頂けますと幸いです。

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

処理に時間がかかる

該当のソースコード

Ruby

1kakaku = CSV.read("data/kudamono.csv", headers: true) 2k = 0 350000.times{ 4 if kakaku[k]["date/time"] ==  ”検索したい日付を入力” 5  puts csv[k] 6 end 7 k += 1 8}

補足情報(FW/ツールのバージョンなど)

使用しているソフトはRubyMineです。全て独学なので基礎が抜けているかもしれません。

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

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

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

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

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

jun68ykt

2018/07/16 16:11

前提を確認させてください。kudamono.csv のデータ行は、左から2カラム目の日付(date)の昇順で、あらかじめソートされているものと考えてよいでしょうか?ご質問に書かれている、「保存してあるCSVファイル(ファイル名:kudamono.csv)」を見る限りでは、そのように思えたのですが、念のための確認です。
otn

2018/07/16 16:33

ファイルから一度読み込んだデータに対して、検索を何度も繰り返したいということでしょうか?
退会済みユーザー

退会済みユーザー

2018/07/16 23:44

jun68ykt >はい。左から2カラム目の日付(date)の昇順です。ちなみに2カラム目の日付で同じ日付が複数ある場合の次の優先順位は特にありません。 otn> ファイルを一度読み込んでも、その都度ファイルを読み込んでもかまいません。 日付の検索は日付を変えて何度も(数千回)するので、その都度ファイルを読み込むより一旦読み込んだ方が早いかなと思い今の処理です。
guest

回答2

0

ベストアンサー

ファイルを一度読み込んでも、その都度ファイルを読み込んでもかまいません。 日付の検索は日付を変えて何度も(数千回)するので、その都度ファイルを読み込むより一旦読み込んだ方が早いかなと思い今の処理です。

検索を速くするには、前準備が必要です。
同じデータで多数回検索を行うのであれば、前準備に割く時間は無視できるようになります。
1回あたりの検索時間=1検索の処理に掛かる時間+前準備時間÷検索回数

という意図で質問しました。
あとは、データがメモリに乗り切るかどうかですね。

メモリに乗り切らないのであれば、DBMSに入れる必要があります。Rubyだけで出来る簡易DBMSみたいなものもあります(DBMクラス)。
メモリに載り切る量であれば、ハッシュが簡単でしょう。

Ruby

1data = Hash.new{|h,k| h[k]=[]} 2CSV.foreach("data/kudamono.csv", headers: true) do |row| 3 data[row["date"]] << row 4end 5 6search = "20190101" 7p data[search] 8 9search = "20190102" 10p data[search]

投稿2018/07/17 00:50

otn

総合スコア84555

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

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

退会済みユーザー

退会済みユーザー

2018/07/17 15:35

ありがとうございます!ご教授頂いたハッシュの方法で処理スピードが格段に速くなりました。 しかしなぜハッシュにするとスピードが速くなるのでしょうか? 配列だと一つ一つ検索するが、ハッシュだとキーのみ検索するからでしょうか? それだとしても、キーのみの場合と、配列一つ一つの場合のデータ個数はさほどかわりません。 速くなったはいいものの、理由がわかりません。。。
asm

2018/07/18 00:04

group_byでいいような気がします
otn

2018/07/18 09:09

> group_byでいいような気がします そうですね。 data = CSV.read("data/kudamono.csv", headers: true).group_by{|x| x["date"]} どうも富豪的プログラミングならぬ、貧乏人プログラミングが染みついています。
退会済みユーザー

退会済みユーザー

2018/07/21 04:18

参考になりました。ありがとうございます!
guest

0

いくつかのアイデアがあります。

1. {日付け => [行データの配列]}のような hash をつくる。

2. csv の内容を DB に登録する。日付けに index を張る。

投稿2018/07/16 22:30

編集2018/07/17 14:10
katoy

総合スコア22324

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

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

退会済みユーザー

退会済みユーザー

2018/07/16 23:40

1. {日付け => [行データの配列]}のような hash をつくる。 これを作り具体的にどのようにすると検索が早くなるのでしょうか? ちなみに実際に日付が重なっているデータは多くても5つ程で、平均は1〜2かと思うので、ハッシュの数は40000個程出来ると思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問