teratail header banner
teratail header banner
質問するログイン新規登録
Ruby

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

Q&A

解決済

2回答

2588閲覧

rubyで複数列のデータを1行に列ごとにつなげるコードを知りたいです

sakuya_izayoi

総合スコア19

Ruby

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

0グッド

1クリップ

投稿2017/01/14 13:45

編集2017/01/14 14:51

0

1

rubyを用いたプログラムで、複数列のデータを1行にまとめる方法を知りたいです。
rubyというプログラムの勉強中です。
テキストファイルの出力に関してなのですが、質問させてください。以下の様なデータがあり、一列当たりはスペース含め40文字で区切られているprnファイルであります。

それを縦方向に積み重ねていくというプログラムを組もうとしました。以下がその例です。
1,2,1, 2,2,1, 3,2,1,
X方向_変位0.01 X方向_変位0.02 X方向_変位0.03
0,0,0, 0,0,0, 0,0,0,
2,0,0,0,0,0,0,0,0,0, 2,0,0,0,0,0,0,0,0,0, 2,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,
1,2,2,7, 1,2,2,7, 1,2,2,7,
0,1,1, 0,1,1, 0,1,1,
1,data1, 1,data2, 1,data3,
2,data1, 2,data2, 2,data3,
3,data1, 3,data2, 3,data3,
4,data1, 4,data2, 4,data3,
5,data1, 5,data2, 5,data3,
6,data1, 6,data2, 6,data3,
7,data1, 7,data2, 7,data3,
8,data1, 8,data2, 8,data3,
9,data1, 9,data2, 9,data3,
10,data1, 10,data2, 10,data3,
11,data1, 11,data2, 11,data3,
12,data1, 12,data2, 12,data3,
13,data1, 13,data2, 13,data3,
14,data1, 14,data2, 14,data3,
15,data1, 15,data2, 15,data3,
-1,0, -1,0, -1,0,

であります。(スペース区切りの前にカンマがありますが、これは区切り文字ではなく、あくまでスペースで区切られております) 列の長さは不定であり、データ列間は半角スペースのみで区切られております。
上記のようなデータを

1,2,1,
X方向_変位0.01
0,0,0,
2,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
1,2,2,7,
0,1,1,
1,data1,
2,data1,
3,data1,
4,data1,
5,data1,
6,data1,
7,data1,
8,data1,
9,data1,
10,data1,
11,data1,
12,data1,
13,data1,
14,data1,
15,data1,
-1,0,
2,2,1,
X方向_変位0.02
0,0,0,
2,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
1,2,2,7,
0,1,1,
1,data2,
2,data2,
3,data2,
4,data2,
5,data2,
6,data2,
7,data2,
8,data2,
9,data2,
10,data2,
11,data2,
12,data2,
13,data2,
14,data2,
15,data2,
-1,0,
3,2,1,
X方向_変位0.03
0,0,0,
2,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
1,2,2,7,
0,1,1,
1,data3,
2,data3,
3,data3,
4,data3,
5,data3,
6,data3,
7,data3,
8,data3,
9,data3,
10,data3,
11,data3,
12,data3,
13,data3,
14,data3,
15,data3,
-1,0,
4,2,1,
X方向_変位0.04
0,0,0,
2,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
1,2,2,7,
0,1,1,
1,data4,
2,data4,
3,data4,
4,data4,
5,data4,
6,data4,
7,data4,
8,data4,
9,data4,
10,data4,
11,data4,
12,data4,
13,data4,
14,data4,
15,data4,
-1,0,
以下続く

と重ねたいという意味です。
自分で組んだところ、一列目のみが出力されて、二列目三列目のデータが出力されませんでした。
二列目以降がうまく取得できていないのですが、サンプルというよりはこのように組めば大丈夫というプログラムの答えが知りたいです。なお、本当のファイルは横に多いと1000列で1万行近くになります。そのため、私が一番得意なVBAでは作業ができず困っております。巨大なファイルが操れるrubyやphysonならできるのではないかと思っての質問です。

この完成したファイルをファイル②とすると、その前にファイル①を加え、ファイル②の後ろにファイル③を付け加えたファイル完成版というのを作ることも可能なのでしょうか?というのも、とてつもなくファイルが大きくなってテキストエディタではファイル②を編集することも困難になりそうだからです。

よろしくお願いします。

修正追記
ご指摘を受けましては、2行目の部分に余分なスペースが入っていたのを修正いたしました。このデータは一列あたり 半角39文字+区切り用半角スペース1文字の40カラム型であり、半角39文字に足りていない箇所には39文字となるように強制的に半角スペースが挿入される仕様になっております。その上で区切り半角スペース1文字追加で40カラムとなります。

追記事項としまして、このデータは数値解析結果なのですが、スペース区切りではなく、一列あたり半角40文字でタブ区切りという形も出力出来るようなのですが、rubyではスペース区切りとタブ区切りのどちらの方が操りやすいでしょうか?(40文字の半角+tab区切り)

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

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

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

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

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

otn

2017/01/14 13:57

2行目が、空白区切りだと6列になりますが、この行だけ特別扱いですか?
sakuya_izayoi

2017/01/14 14:23

いえ、掲示板に貼り付けた都合上スペースがおかしくなっているのですが、実際のファイルは一列当たりは39文字+半角スペース1文字の40カラムであります。
otn

2017/01/14 14:30

ではちゃんと貼り付けてください。
otn

2017/01/14 15:03

改行で区切られた行じゃなくて、改行無しの1レコード40文字の固定長レコードファイルと言うことですか?
otn

2017/01/14 15:06

あと、「自分で組んだところ、」というプログラムも載せた方が良いですね。
sakuya_izayoi

2017/01/14 16:29 編集

固定長のレコードでございます。あと、文面からではrubyで組んだと誤認させることとなっており申し訳ありません。これはvbaで組んだものであります。rubyなら出来るのでは無いかと思った理由も解析プログラムがrubyで動いているのが分かったからであります。自分ではrubyのじゃんけんゲーム程度しかまだ組めず、ファイル操作を今学習している所であり、答えから分解して学習しているところでもあります。
otn

2017/01/14 23:44

固定長というのは良いのですが、行の区切りの改行は存在するのですか?
sakuya_izayoi

2017/01/15 01:09

おはようございます。行区切りの改行はワードなどでいうEnterキーでできる「改行」マークになっております。(Shift]+[Enter]で改行すると「↓」の改行マークではない) です。よろしくお願いします。
guest

回答2

0

2行目だけ除外して考えると、全行が3要素なので、配列に読み込んでtranspose(転置行列)でいいです。

Ruby

1puts ARGF.map{|line| line.chomp.split(/ /)}.transpose

2行目だけ特別扱いするとなると、6要素を2つずつ組にしてくっつけます。

Ruby

1puts ARGF.map{|line| 2 if /X方向_変位/ =~ line 3 line.chomp.split(/ /).each_slice(2).map{|x| x.join(" ")} 4 else 5 line.chomp.split(/ /) 6 end 7}.transpose

メモリに入りきらないくらいのファイルサイズだとすると、ファイルを3回読むと言うことになりますね。

#質問コメントを見ての追記
改行で区切られており、末尾に空白が詰まっていると言うことであれば、最初のプログラムの改善で、

Ruby

1puts ARGF.map{|line| line.rstrip.split(/ /)}.transpose

コマンドラインから、

Bash

1ruby -e "puts ARGF.map{|line| line.rstrip.split(/ /)}.transpose" 入力ファイル > 出力ファイル

で。

投稿2017/01/14 14:13

編集2017/01/15 02:27
otn

総合スコア86354

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

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

0

ベストアンサー

変換結果をファイルに保存するようにしてみました。
さらに、変換結果(out.txt) を元のファイル形式(out2.txt) に戻す処理も書き、それが最初のデータ内容(data.txt) とも一致することを確認しました。

r.rb

ruby

1require 'csv' 2 3in_file = 'data.txt' 4out_file = 'out.txt' 5out_file2 = 'out2.txt' 6SEP = ' '.freeze 7 8arrs = CSV.table(in_file, col_sep: SEP, headers: %w(1 2 3)) 9 10CSV.open(out_file, 'wb', col_sep: SEP) do |csv| 11 arrs.by_col!.headers.each do |col| 12 arrs[col].each { |item| csv << [item] } 13 end 14end 15 16items = File.readlines(out_file).map(&:chomp) 17CSV.open(out_file2, 'wb', col_sep: SEP) do |csv| 18 num = items.size 19 base1 = num / 3 20 base2 = base1 * 2 21 (0...(num / 3)).each do |i| 22 csv << [items[i], items[base1 + i], items[base2 + i]] 23 end 24end

実行例

$ cat data.txt 1,2,1, 2,2,1, 3,2,1, X方向_変位0.01 X方向_変位0.02 X方向_変位0.03 0,0,0, 0,0,0, 0,0,0, 2,0,0,0,0,0,0,0,0,0, 2,0,0,0,0,0,0,0,0,0, 2,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 1,2,2,7, 1,2,2,7, 1,2,2,7, 0,1,1, 0,1,1, 0,1,1, 1,data1, 1,data2, 1,data3, 2,data1, 2,data2, 2,data3, 3,data1, 3,data2, 3,data3, 4,data1, 4,data2, 4,data3, 5,data1, 5,data2, 5,data3, 6,data1, 6,data2, 6,data3, 7,data1, 7,data2, 7,data3, 8,data1, 8,data2, 8,data3, 9,data1, 9,data2, 9,data3, 10,data1, 10,data2, 10,data3, 11,data1, 11,data2, 11,data3, 12,data1, 12,data2, 12,data3, 13,data1, 13,data2, 13,data3, 14,data1, 14,data2, 14,data3, 15,data1, 15,data2, 15,data3, -1,0, -1,0, -1,0, $ ls *.txt data.txt $ ruby r.rb $ ls *.txt data.txt out.txt out2.txt $ cat out.txt 1,2,1, X方向_変位0.01 0,0,0, 2,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 1,2,2,7, 0,1,1, 1,data1, 2,data1, 3,data1, 4,data1, 5,data1, 6,data1, 7,data1, 8,data1, 9,data1, 10,data1, 11,data1, 12,data1, 13,data1, 14,data1, 15,data1, -1,0, 2,2,1, X方向_変位0.02 0,0,0, 2,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 1,2,2,7, 0,1,1, 1,data2, 2,data2, 3,data2, 4,data2, 5,data2, 6,data2, 7,data2, 8,data2, 9,data2, 10,data2, 11,data2, 12,data2, 13,data2, 14,data2, 15,data2, -1,0, 3,2,1, X方向_変位0.03 0,0,0, 2,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 1,2,2,7, 0,1,1, 1,data3, 2,data3, 3,data3, 4,data3, 5,data3, 6,data3, 7,data3, 8,data3, 9,data3, 10,data3, 11,data3, 12,data3, 13,data3, 14,data3, 15,data3, -1,0, $ diff data.txt out2.txt $ cat out2.txt 1,2,1, 2,2,1, 3,2,1, X方向_変位0.01 X方向_変位0.02 X方向_変位0.03 0,0,0, 0,0,0, 0,0,0, 2,0,0,0,0,0,0,0,0,0, 2,0,0,0,0,0,0,0,0,0, 2,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 1,2,2,7, 1,2,2,7, 1,2,2,7, 0,1,1, 0,1,1, 0,1,1, 1,data1, 1,data2, 1,data3, 2,data1, 2,data2, 2,data3, 3,data1, 3,data2, 3,data3, 4,data1, 4,data2, 4,data3, 5,data1, 5,data2, 5,data3, 6,data1, 6,data2, 6,data3, 7,data1, 7,data2, 7,data3, 8,data1, 8,data2, 8,data3, 9,data1, 9,data2, 9,data3, 10,data1, 10,data2, 10,data3, 11,data1, 11,data2, 11,data3, 12,data1, 12,data2, 12,data3, 13,data1, 13,data2, 13,data3, 14,data1, 14,data2, 14,data3, 15,data1, 15,data2, 15,data3, -1,0, -1,0, -1,0,

投稿2017/01/15 01:11

katoy

総合スコア22328

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

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

sakuya_izayoi

2017/01/15 03:16

望んでいた通りのものであります。 教えてほしいことがあります。 CSV.open(out_file, 'wb', col_sep: SEP) do |csv| の部分で、col_sep: SEPのところでスペース区切りであると指示していると思うのですが、 作っていただいたコードで 1,2,1, 2,2,1, 3,2,1, X方向_変位0.01 X方向_変位0.02 X方向_変位0.03 0,0,0, 0,0,0, 0,0,0, 2,0,0,0,0,0,0,0,0,0, 2,0,0,0,0,0,0,0,0,0, 2,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 1,2,2,7, 1,2,2,7, 1,2,2,7, 0,1,1, 0,1,1, 0,1,1, 1,data1, 1,data2, 1,data3, 2,data1, 2,data2, 2,data3, 3,data1, 3,data2, 3,data3, 4,data1, 4,data2, 4,data3, 5,data1, 5,data2, 5,data3, 6,data1, 6,data2, 6,data3, 7,data1, 7,data2, 7,data3, 8,data1, 8,data2, 8,data3, 9,data1, 9,data2, 9,data3, 10,data1, 10,data2, 10,data3, 11,data1, 11,data2, 11,data3, 12,data1, 12,data2, 12,data3, 13,data1, 13,data2, 13,data3, 14,data1, 14,data2, 14,data3, 15,data1, 15,data2, 15,data3, -1,0, -1,0, -1,0, の場合と 1,2,1, 2,2,1, 3,2,1, X方向_変位0.01 X方向_変位0.02 X方向_変位0.03 0,0,0, 0,0,0, 0,0,0, 2,0,0,0,0,0,0,0,0,0, 2,0,0,0,0,0,0,0,0,0, 2,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 1,2,2,7, 1,2,2,7, 1,2,2,7, 0,1,1, 0,1,1, 0,1,1, 1,data1, 1,data2, 1,data3, 2,data1, 2,data2, 2,data3, 3,data1, 3,data2, 3,data3, 4,data1, 4,data2, 4,data3, 5,data1, 5,data2, 5,data3, 6,data1, 6,data2, 6,data3, 7,data1, 7,data2, 7,data3, 8,data1, 8,data2, 8,data3, 9,data1, 9,data2, 9,data3, 10,data1, 10,data2, 10,data3, 11,data1, 11,data2, 11,data3, 12,data1, 12,data2, 12,data3, 13,data1, 13,data2, 13,data3, 14,data1, 14,data2, 14,data3, 15,data1, 15,data2, 15,data3, -1,0, -1,0, -1,0, とで同じに結果になるというのが理解できません。 最初の方であると、区切りスペースが半角1文字と認識していると思ったのですが、スペースが続く限りは区切りが継続していると判断してくれているのでしょうか?
sakuya_izayoi

2017/01/15 03:21

上記のコメントですが投稿すると、上の方の並びと下の方の並びが区別つかなくなってしまいました。 下の方の文字列は1列40字の固定長であり、不足している部分は半角スぺース詰めになっております。
katoy

2017/01/15 05:40

col_sep: " " と指定すると "1 2 3" "1 2 3 " のどちららも "1", "2", "3" の 3 項目として認識されます。 次の例をご覧ください。 $ cat data1.txt // 空白1文字で区切る、行末尾に空白なし 1 2 3 a b c A B C $ cat data2.txt // 空白 3 つで区切る、行の末尾に 空白 3 つがある 1 2 3 a b c A B C $ cat rr.rb require 'csv' in_file_1 = 'data1.txt' in_file_2 = 'data2.txt' SEP = ' '.freeze arrs = CSV.table(in_file_1, col_sep: SEP, headers: %w(1 2 3)) arrs.by_col!.headers.each { |col| p arrs[col] } puts arrs = CSV.table(in_file_2, col_sep: SEP, headers: %w(1 2 3)) arrs.by_col!.headers.each { |col| p arrs[col] } $ ruby rr.rb [1, "a", "A"] [2, "b", "B"] [3, "c", "C"] [1, "a", "A"] [2, "b", "B"] [3, "c", "C"]
sakuya_izayoi

2017/01/15 06:01

なるほど、空白部分は全部分割記号であると認識してくれているわけですね。 例題を示してくださり、わかりやすかったです。
katoy

2017/01/15 06:14

teratail のコメント中では、 連続した空白や文末の空白が勝手に圧縮れたり、削除されてしまうようですね。 空白文字について議論するときは、とても不便です。...
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.30%

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

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

質問する

関連した質問