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

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

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

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

Q&A

解決済

3回答

3118閲覧

特定の文字列で配列を分割したい(1つのテキストファイルを章別に分割したい)

Sakky0206

総合スコア8

Ruby

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

0グッド

0クリップ

投稿2015/03/02 15:18

編集2015/03/03 14:29

lang

1scn_array =[] 2chapter_array =[] 3# シナリオテキストを配列に格納 4File.open("scenario.txt", "r") do |file| 5 file.each do |line| 6 scn_array << line 7 end 8end 9 10# 章分けマーク「■」で配列を分ける(2次元配列) 11chapter_array = scn_array.slice_before(/^■/).to_a

シナリオ全文を1つのテキストファイル(scenario.txt)にまとめています。
これを改行記号ごとに区切りをつけ、一つの配列「scn_array」に格納しました。

一方、テキストファイルは行頭に「■第1章」、「■第2章」のように「■」をつけており、
これを区切りとして、章別の配列を作ろうとしているのですが、うまくいきません。

上記コードでは「.slice_before(/^■/).to_a」メソッドを用いて、「scn_array」を
2次元配列「chapter_array」に格納した後、どうにか
event_array1 = chapter_array[0]
event_array2 = chapter_array[1]...
というように配列を章別に分割したいのですが……。
うまいやり方をご教示いただきたく思います。
(上記のようにevent_array+"number"をすれば可能といえば可能ですが)


3/3追記

すいません。コード書くので手一杯で肝心の質問内容が不明確でした。

目的は一定の書式で書かれたテキストファイルをノベルゲーム用の
ミドルウェアで読み込める形式に変換することです。

ゲーム形式は全画面にテキストではなく、画面したにメッセージウィンドウが表示されるタイプです。

テキストファイルは
・ファイル名は「tarou.txt」のように「キャラ名.txt」で、
ファイルの中身は下記のような書式で書いています。

lang

1//太郎シナリオ 2■ルートA(HappyRoute) 3◎イベント1(A-1) 4//背景:公園 5//音楽:曲目1 6 7◆太郎 8あいうえおかきくけこ 9さしすせそたちつてと 10 11◆花子 12いろはにほへと、ちり 13 14●場面転換 15//背景:町 16//音楽:曲目2 17 18◆次郎 19はろー 20 21◆三郎 22ちゃお 23 24◎イベント2 25(以下略) 26 27 28■ルートB(NormalRoute) 29◎イベント1(B-1) 30(以下略)

これをrubyのプログラムを通して
・TARO-HAP-EVE1.mid
・TARO-HAP-EVE2.mid
(中略)
・TARO-BAD-EVE4.mid
(以下、次郎、三郎シナリオテキスト加工へ)
とファイルを分割した上で、個々のファイルを

lang

1 2 3[EVENT_START] # 開始処理 4BG:PARK.png 5BGM:MUSIC1.mp3 6 7message_window_open 8talk(TARO_WARAI, RIGHT) 9>太郎 # > は台詞の始まり 10あいうえおかきくけこ 11さしすせそたちつてと★ # ★で改ページ 12 13talk(HANAKO_IKARI, LEFT) 14>花子 15いろはにほへと、ちり★ 16 17[SCENE_CHANGE] # 画面をブラックアウトなど場面転換処理 18BG:TOWN 19BGM:MUSIC2.mp3 20[SCENE_CHANGE_END] 21 22talk(JIRO_JOY, RIGHT) 23>次郎 24はろー★ 25 26talk(SABURO_CRY, LEFT) 27>三郎 28ちゃお★ 29 30[EVENT_END] # 終了処理 31

のように加工し、出力しようと思っています。
現在やっていることは
・シナリオ入力フォルダからテキストファイルのリストを受け取る
・「キャラ名.txt」を個別に加工する
・シナリオ出力フォルダに出力する
というような感じです。

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

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

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

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

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

guest

回答3

0

結局、ブロック構造がまだうまくできず、Perlで上記目的を達成しました。
アドバイスしていただき、ありがとうございました。

投稿2015/03/10 01:30

Sakky0206

総合スコア8

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

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

0

コメントにはコードが書きづらいので別の回答にします。

(やり方がまずいのかもしれません)

そうですね。
こんな感じでしょうか。

lang

1require "pp" 2chapter_array = IO.readlines("scenario.txt").slice_before(/^■/).to_a 3pp chapter_array 4event_array = chapter_array.map do |chapter| 5 chapter.slice_before(/^◎/).to_a 6end 7pp event_array

2次元配列のままですと幾重にも加工しようとするとごちゃごちゃになりそうなので、

2次元配列は、1次元配列の1次元配列なので、段階を踏んで考えればいです。

あるいは、そもそも1行1行を配列要素にする必要があるのか?
全体を1つの文字列にしてそれを分割するという方法もあります。

lang

1require "pp" 2 3chapter_array = IO.read("scenario.txt").split(/(?=^■)/) #全体を読み込んで行頭の四角の手前で分割 4pp chapter_array 5event_array = chapter_array.map do |chapter| #各チャプターの内容を 6 chapter.split(/(?=^◎)/) #行頭の二重丸の手前で分割 7end 8pp event_array

分割した後、最終的にはファイルに書くんですか?どこを区切りにするんでしょう?
追記を見てもよくわかりません。

投稿2015/03/03 13:02

otn

総合スコア84538

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

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

0

ベストアンサー

.slice_before(/^■/).to_aで、章別に分割されていると思うのですが、分割した後どうしたいということでしょうか?

あと、質問の答では無いですが、上記の前半は1行でかけます。

lang

1scn_array = IO.readlines("scenario.txt")

投稿2015/03/02 15:39

otn

総合スコア84538

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

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

Sakky0206

2015/03/02 16:36

返答ありがとうございます。 >分割した後どうしたいということでしょうか? ノベルゲーム用にテキスト加工するためです。 分割した後、さらに節別に配列を分け、節の配列を加工する予定です。 例えば、節を示す行頭「◎」でさらにわけて、 「◎」に「A1」、「A2」番号をふる、などを考えています。 思いつきですが、配列ではなくハッシュの方がうまくいく気がしてきました。 chapter_hash = Hash.new each.with_index(1) do |n, idx| chapter[idx] = n end >あと、質問の答では無いですが、上記の前半は1行でかけます。 ありがとうございます。別の用途で短くしたかったので助かります。
otn

2015/03/02 16:41

>分割した後、さらに節別に配列を分け、節の配列を加工する予定です。 同じように、slice_beforeで分割できると思うのですが、なにが問題と感じていますか? >each.with_index(1) do |n, idx| >chapter[idx] = n だと、配列と変わりませんね。スタートが0でなく1なだけで。
Sakky0206

2015/03/03 04:53

たびたびありがとうございます。 >同じように、slice_beforeで分割できると思うのですが、なにが問題と感じていますか? 2次元配列chapter_array([[■,◎,◎,◎][■,◎,◎]])を event_array = chapter_array.slice_before.to_a のようにさらに◎でslice_beforeすると event_array => [[■,◎,◎,◎,■,◎,◎],nil,nil,] となってしまいます。 (やり方がまずいのかもしれません) ただ、2次元配列のままですと幾重にも加工しようとするとごちゃごちゃになりそう なので、chapter_arrayを下記のように1次元配列event_arrayにそれぞれ格納したいと 考えていますが、ここが全然うまくいっていません。 event_array1([■,◎,◎,◎])、event_array2([■,◎,◎])と こうした上で例えば、節番号をつけるコードをかけば、「第1章1節、第2章1節……」 と加工がやりやすくなると思い、トライしています。chapter_arrayのままでは、 ◎が出るたびに節番号をつけてしまうといった想定外の問題が発生しそうなので。 event_array.each do |line| file_num = 1 case line when /^◎/ file_num +=1 end end
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問