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

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

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

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

Ruby

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

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

2回答

3429閲覧

Ruby:二つのcsvファイルの差分データを配列に格納したい。

sss_kdo

総合スコア7

CSV

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

Ruby

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

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

0クリップ

投稿2019/01/15 03:21

編集2019/01/15 11:48

前提・実現したいこと

Ruby初心者です。

前提・実現したいこと
Rubyで二つのcsvファイル比較して、新しく追加されたレコードのみを配列に格納したい。

【問題点】
新しく追加された配列のデータの要素を配列に格納する機能を実装中に以下のエラーメッセージが発生しました。

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

`block in <main>': undefined method `<' for nil:NilClass (NoMethodError)

該当のソースコード

Ruby

1#encoding: SJIS 2#lib 3require 'csv' 4require 'diff/lcs' 5 6#var_num 7checkonlynewdiff = Array.new() 8newolddiff = Array.new() 9 10puts "start..." 11 12#read csvfile(old&new) 13data1 = CSV.read "csvtestold.csv" 14data2 = CSV.read "csvtestnew.csv" 15 16#diff_old&new read_csv_data 17diffs = Diff::LCS.diff(data1, data2) 18 19diffs.each do |diff| 20 diff.each do |line| 21 newolddiff << line.to_a 22 end 23end 24 25#purpose:read only diff_new_add_data 26newolddiff.each_index{|idx| 27 if newdiff[idx][0] == "+" 28 #happen to error message 29 checkonlynewdiff << newolddiff[idx][3] 30 end 31} 32puts "end..."

試したこと

メソッドが存在しないのがエラー原因と書かれているので、@newdiff[idx][3].to_aにして試したが駄目でした。

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

Ruby:2.5.2
Ruby library install:gem install diff-lcs
OS:Windows10
csvファイル
csvtestold.csv------
name,id,date
sho,220,2018/1/5
akiho,221,2018/1/6
sss, 222,2018/1/7

csvtestnew.csv------
name,id,date
akiho,221,2018/1/6
sss, 222,2018/1/7
kdo,223,2018/1/8
shi,224,2018/1/9
skd,225,2018/1/10

参考URL
(rubyの変数について)
https://qiita.com/nakamaru/items/1339303487fe8a876825

(Class: Diff::LCS::Change)
https://www.rubydoc.info/gems/diff-lcs/1.2.5/Diff/LCS/Change

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

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

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

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

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

guest

回答2

0

ベストアンサー

変数の使い方が間違えてる云々は割愛して...
typoがかなり多くて云々も割愛して...

いくつか...

bash

1NoMethodError (undefined method `<<' for nil:NilClass)

このエラーの発生は変数の使い方が間違っているというのに起因しています。

ruby

diffs = Diff::LCS.diff(@@data1, @@data2)

この部分は正常に動けば

ruby

1#=> [[["-", 13, "s"], ["+", 13, "a"], ["+", 14, "k"], ["+", 15, "i"]], [["+", 21, "1"], ["+", 22, ","], ["+", 23, "2"]], [["+", 25, "1"], ["+", 26, "8"], ["+", 27, "/"], ["+", 28, "1"], ["+", 29, "/"], ["+", 30, "6"], ["+", 31, "\n"], ["+", 32, "s"], ["+", 33, "s"], ["+", 34, "s"]], [["+", 37, "2"], ["+", 38, "2"], ["+", 39, ","], ["+", 40, "2"]], [["-", 28, "5"], ["+", 47, "7"]], [["-", 30, "a"]], [["-", 32, "i"], ["-", 33, "h"], ["+", 50, "d"]], [["-", 38, "1"], ["+", 55, "3"]], [["-", 47, "6"], ["+", 64, "8"]], [["-", 50, "s"], ["-", 51, "s"], ["+", 67, "h"], ["+", 68, "i"]], [["+", 72, "4"], ["+", 73, ","]], [["+", 75, "0"], ["+", 76, "1"], ["+", 77, "8"], ["+", 78, "/"], ["+", 79, "1"], ["+", 80, "/"], ["+", 81, "9"], ["+", 82, "\n"], ["+", 83, "s"], ["+", 84, "k"], ["+", 85, "d"]], [["+", 88, "2"], ["+", 89, "5"], ["+", 90, ","], ["+", 91, "2"]], [["-", 64, "7"], ["+", 98, "1"], ["+", 99, "0"]]]

こんな感じで返って来ると思いますが、これは期待する値なのでしょうか...

ruby

diffs.each do |diff|
diff.each do |line|
@@newolddiff << line.to_a
end
end

わざわざArrayにする必要を感じません。

以上を踏まえて少し書いてみました。
できればコピペして解決〜なんてのは避けて欲しいです。
もしこれが望み通りの結果であれば、理解できていなかった部分を調べ直して経験値としていただければ幸いです。

ruby

1require 'csv' 2require 'diff/lcs' 3 4checkonlynewdiff = [] 5 6data1 = <<~EOS 7 name,id,date 8 sho,220,2018/1/5 9 akiho,221,2018/1/6 10 sss,222,2018/1/7 11 EOS 12data2 = <<~EOS 13 name,id,date 14 akiho,221,2018/1/6 15 sss,222,2018/1/7 16 kdo,223,2018/1/8 17 shi,224,2018/1/9 18 skd,225,2018/1/10 19 EOS 20 21diffs = Diff::LCS.diff(data1.split("\n"), data2.split("\n")) 22#=> [[["-", 1, "sho,220,2018/1/5"]], [["+", 3, "kdo,223,2018/1/8"], ["+", 4, "shi,224,2018/1/9"], ["+", 5, "skd,225,2018/1/10"]]] 23 24diffs.flatten.each do |diff| 25 checkonlynewdiff << diff.element if diff.adding? 26end 27 28p checkonlynewdiff 29#=> ["kdo,223,2018/1/8", "shi,224,2018/1/9", "skd,225,2018/1/10"] 30 31#ちなみに最後の部分は一発で取ることもできる 32diffs.flatten.select(&:adding?).map(&:element) 33#=> ["kdo,223,2018/1/8", "shi,224,2018/1/9", "skd,225,2018/1/10"]

投稿2019/01/15 05:37

編集2019/01/15 09:13
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

sss_kdo

2019/01/15 09:07

指摘ありがとうございます。 期待する値は新しく追加されたデータの部分のみなので、 >#=> ["kdo,223,2018/1/8", "shi,224,2018/1/9", "skd,225,2018/1/10"]を抽出したかったです。 質問なのですが、実行すると >diffs.each do |diff| > checkonlynewdiff << diff.element if diff.adding? >end の箇所で、以下のエラーメッセージが返ってきました。 =>undefined method `adding?' for [["-", 1, "sho,220,2018/1/5"]]:Array (NoMethodError) buta_bottiさんの環境では動作できていますか?
退会済みユーザー

退会済みユーザー

2019/01/15 09:09 編集

最後の指摘箇所、Arrayに変更する必要を云々の部分の違いだと思います。 sss_kdoさんのコードではまだ配列に変換している処理が残っているんじゃないですかね?
退会済みユーザー

退会済みユーザー

2019/01/15 09:12

あぁ、すみません僕のミスでした。 .flattenが抜けてますね... 修正しておきます。
sss_kdo

2019/01/15 10:02 編集

修正ありがとうございます。正常に動作しました。 僕の理解が追い付いてなくて何が駄目なのかわかっていなかったです。=>flattenを勉強します。 もう一点質問したいです。 diff/lcs標準ライブラリではないのですが、buta_bottiさんはよく使われているのですか?
退会済みユーザー

退会済みユーザー

2019/01/15 10:08

flattenよりまず変数の使い方を学ぶべきです。 今回のエラーも変数の使い方がまずいが故に起きたものですし... flattenなんてメソッドは知らなくてもたいして困らないので優先度は低いですよ。 diff/lcs は今日初めて使いました。
sss_kdo

2019/01/15 10:25

わかりました。 まずは基本的な箇所から勉強していきます。 diff/lcs初めて使うのに、対応してくれてありがとうございます。
guest

0

唐突に、@checkdiffという変数が出てきていますが、これは何ですか?もしかして、@checkonlynewdiffの間違いでは?

あと、インスタンス変数が間違った使われ方をしています。

投稿2019/01/15 03:42

otn

総合スコア84555

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

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

otn

2019/01/15 04:03

@newolddiff[idx][3] も @newolddiff[idx][2] の間違いでしょうね。
sss_kdo

2019/01/15 04:20 編集

指摘ありがとうございます。 @checkonlynewdiffに直しました。 インスタンス変数はインスタンス生成時に使うんですね! じゃあここでは、クラス変数に直した方がいいってことですよね?
sss_kdo

2019/01/15 04:10

@newolddiff[idx][3]は合ってると思うんですけどね。 今、外出中なので、家に帰ったら試してみます!
otn

2019/01/15 04:24

> じゃあここでは、クラス変数に直した方がいいってことですよね? いえ。普通のローカル変数を使います。
sss_kdo

2019/01/15 08:55

勉強不足ですみません。 基本的なところから勉強しなおしていきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問