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

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

ただいまの
回答率

90.34%

  • Ruby

    8234questions

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

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

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 843

sakuya_izayoi

score 13

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区切り)

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • sakuya_izayoi

    2017/01/15 01:26 編集

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

    キャンセル

  • otn

    2017/01/15 08:44

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

    キャンセル

  • sakuya_izayoi

    2017/01/15 10:09

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

    キャンセル

回答 2

+1

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

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


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

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

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

質問コメントを見ての追記

改行で区切られており、末尾に空白が詰まっていると言うことであれば、最初のプログラムの改善で、

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


コマンドラインから、

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


で。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

checkベストアンサー

0

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

r.rb

require 'csv'

in_file = 'data.txt'
out_file = 'out.txt'
out_file2 = 'out2.txt'
SEP = ' '.freeze

arrs = CSV.table(in_file, col_sep: SEP, headers: %w(1 2 3))

CSV.open(out_file, 'wb', col_sep: SEP) do |csv|
  arrs.by_col!.headers.each do |col|
    arrs[col].each { |item| csv << [item] }
  end
end

items = File.readlines(out_file).map(&:chomp)
CSV.open(out_file2, 'wb', col_sep: SEP) do |csv|
  num = items.size
  base1 = num / 3
  base2 = base1 * 2
  (0...(num / 3)).each do |i|
    csv << [items[i], items[base1 + i], items[base2 + i]]
  end
end

実行例

$ 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 12: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文字と認識していると思ったのですが、スペースが続く限りは区切りが継続していると判断してくれているのでしょうか?



    キャンセル

  • 2017/01/15 12:21

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

    キャンセル

  • 2017/01/15 14: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"]

    キャンセル

  • 2017/01/15 15:01

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

    キャンセル

  • 2017/01/15 15:14

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

    キャンセル

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

  • ただいまの回答率 90.34%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • Ruby

    8234questions

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