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

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

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

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

配列

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

Q&A

解決済

3回答

730閲覧

rubyで、二重配列を使って表を作り、列を入れ替えたいです

otakurounin

総合スコア25

Ruby

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

配列

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

0グッド

0クリップ

投稿2020/05/01 11:04

編集2020/05/03 10:33

rubyで、家計簿を加工するコードを書きたいです。
もともと家計簿の支出部分を、
1002 サンディ 食品 生鮮食品 1274 現金
1018 サンディ 食品 生鮮食品 2967 現金
1108 サンディ 食品 生鮮食品 2895 現金

というように、
月日 購入先 大分類 小分類 金額 決済手段
というように、タブ区切りの六つの項目で記録していました。
これを、

  1. 月日の前に西暦年をつける

2.並び順を
年月日 金額 決済手段 購入場所 大分類 小分類
に並べ替える。
という加工をしたいです。

ruby

1# 行頭に半角数字4つが並んでいれば、その前に西暦年を追加 2open("kakeibo_new1.txt", "w") do |f| 3 IO.foreach("kakeibo_ex.rb") do |line| 4 line.gsub!(/^(\d{4})/){'2016'+$1 } 5 f.puts line 6 end 7 end 8# 各行をタブで分割し、二重配列にする 9a=[] 10open("kakeibo_new2.txt", "w") do |f| 11 IO.foreach("kakeibo_new1.txt") do |line| 12 b=line.split(/\t/) 13 a.push(b) 14 end 15 end 16# 以下のswapメソッドはHayato OKUMOTO @falcon8823さん作成のもの 17class Array 18 def swap!(a,b) 19 raise ArgumentError unless a.between?(0, self.count-1) && b.between?(0, self.count-1) 20 self[a],self[b]=self[b],self[a] 21 self 22 end 23 def swap(a,b) 24 self.dup.swap!(a,b) 25 end 26end 27 28a.each do |b| 29 swap!(b[1],b[4]) 30end

まず、1はできました。
2については、まずいったんデータ全体を入れ子配列にし、子配列の要素を入れ替えるという形で列の入れ替えをしようと思いました。
そこで、配列の要素の入れ替えについては、ネット上で公開されていた、Arrayクラスにメソッドを追加するという形でやろうとしたのですが、
そのメソッドを使っての実行段階で、「メソッドが定義されていない」というエラーが出ます。
swapメソッドはネットで公開されていたものを丸写ししています。

追記
教えていただいたことを参考に、完成させたのが以下のコードです。

ruby

1# 行頭に半角数字4つが並んでいれば、その前に西暦年を追加 2open("kakeibo_new1.txt", "w") do |f| 3 IO.foreach("kakeibo_ex.rb") do |line| 4 line.gsub!(/^(\d{4})/){'2016'+$1 } 5 f.puts line 6 end 7 end 8# 各行をタブで分割し、二重配列にする 9a=[] 10open("kakeibo_new2.txt", "w") do |f| 11 IO.foreach("kakeibo_new1.txt") do |line| 12 line.chomp! 13 b=line.split(/\t/) 14 a.push(b) 15 end 16 end 17# 以下のswapメソッドはHayato OKUMOTO @falcon8823さん作成のもの 18class Array 19 def swap!(a,b) 20 raise ArgumentError unless a.between?(0, self.count-1) && b.between?(0, self.count-1) 21 self[a],self[b]=self[b],self[a] 22 self 23 end 24 def swap(a,b) 25 self.dup.swap!(a,b) 26 end 27end 28p a 29 30a.each do |b| 31 b.swap!(1,4) 32 b.swap!(2,5) 33 b.swap!(3,4) 34 b.swap!(4,5) 35end 36 37open("kakeibo_new3.txt", "w") do |f| 38 a.each do |b| 39 f.puts b.join("\t") 40 end 41end

katoyさんのようにやったほうが明らかに効率出来ですが、最初に作りかけたものも完成させたかったので。
その際に、12行目に
line.chomp!
も入れました。
unexpected /n
というエラーメッセージが出て、何が原因かなかなかわからなかったのですが、ここの改行を取ったらちゃんと動くようになりました。

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

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

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

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

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

guest

回答3

0

ベストアンサー

a.rb

ruby

1infos = [] 2 3File.open('kakeibo.txt', 'rt') do |f| 4 f.each_line do |line| 5 row = line.split 6 infos << { 7 date: "2016#{row[0]}", 8 item: row[1], 9 type: row[2], 10 sub_type: row[3], 11 price: row[4], 12 payment: row[5] 13 } 14 end 15end 16 17open('kakeibo_new.txt', 'w') do |f| 18 infos.each do |info| 19 row = [ 20 info[:date], info[:price], info[:payment], 21 info[:item], info[:type], info[:sub_type] 22 ] 23 f.puts row.join("\t") 24 end 25end

実行例
イメージ説明

投稿2020/05/01 14:06

katoy

総合スコア22324

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

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

otakurounin

2020/05/02 11:59

ありがとうございます。 このように子配列のかわりにハッシュを使うと、何が何だかわかりやすくなりますね。
guest

0

まず質問の部分では、メソッドの使い方を間違えています。Arrayのメソッドで引数は添え字なので、

Ruby

1a.each do |b| 2 b.swap!(1,4) 3end

ですね。意味を理解しないと使えません。
わざわざメソッドを呼ぶほどでもないので、

Ruby

1a.each do |b| 2 b[1],b[4] = b[4],b[1] 3end

でいいと思います。

あとは、大きな改善事項としては、
・いちいちファイルに書かなくていい
・CSVライブラリの使用を検討(CSVという名前だがタブ区切りも当然使える)

細かい改善事項はたくさんあります。

投稿2020/05/01 11:26

otn

総合スコア85901

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

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

otakurounin

2020/05/02 11:54

ありがとうございます。 確かに、よく見るとこのswapメソッドでは引数は添え字ですね。 気が付きませんでした。 それに、確かにメソッドを作らなくても配列要素の交換はできました。
guest

0

こういう時はエラーメッセージを翻訳しないでそのままコピペしたほうが良いです。
「何にメソッドがない」と出ているはず。

swap!(b[1],b[4]) ではなく b.swap!(1,4) では?

投稿2020/05/01 11:14

winterboum

総合スコア23567

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

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

otakurounin

2020/05/02 11:54

ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問