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

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

ただいまの
回答率

88.78%

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

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 2,459

Sakky0206

score 10

scn_array =[]
chapter_array =[]
# シナリオテキストを配列に格納
File.open("scenario.txt", "r") do |file|
  file.each do |line|
    scn_array << line
  end
end

# 章分けマーク「■」で配列を分ける(2次元配列)
chapter_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」で、
ファイルの中身は下記のような書式で書いています。
//太郎シナリオ
■ルートA(HappyRoute)
◎イベント1(A-1)
//背景:公園
//音楽:曲目1

◆太郎
あいうえおかきくけこ
さしすせそたちつてと

◆花子
いろはにほへと、ちり

●場面転換
//背景:町
//音楽:曲目2

◆次郎
はろー

◆三郎
ちゃお

◎イベント2
(以下略)


■ルートB(NormalRoute)
◎イベント1(B-1)
(以下略)
これをrubyのプログラムを通して
・TARO-HAP-EVE1.mid
・TARO-HAP-EVE2.mid
(中略)
・TARO-BAD-EVE4.mid
(以下、次郎、三郎シナリオテキスト加工へ)
とファイルを分割した上で、個々のファイルを
[EVENT_START] # 開始処理
BG:PARK.png
BGM:MUSIC1.mp3

message_window_open
talk(TARO_WARAI, RIGHT)
>太郎 # > は台詞の始まり
あいうえおかきくけこ
さしすせそたちつてと★ # ★で改ページ

talk(HANAKO_IKARI, LEFT)
>花子
いろはにほへと、ちり★

[SCENE_CHANGE] # 画面をブラックアウトなど場面転換処理
BG:TOWN
BGM:MUSIC2.mp3
[SCENE_CHANGE_END]

talk(JIRO_JOY, RIGHT)
>次郎
はろー★

talk(SABURO_CRY, LEFT)
>三郎
ちゃお★

[EVENT_END] # 終了処理
のように加工し、出力しようと思っています。
現在やっていることは
・シナリオ入力フォルダからテキストファイルのリストを受け取る
・「キャラ名.txt」を個別に加工する
・シナリオ出力フォルダに出力する
というような感じです。
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 3

checkベストアンサー

0

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


あと、質問の答では無いですが、上記の前半は1行でかけます。
scn_array = IO.readlines("scenario.txt")

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2015/03/03 01:36

    返答ありがとうございます。

    >分割した後どうしたいということでしょうか?
    ノベルゲーム用にテキスト加工するためです。

    分割した後、さらに節別に配列を分け、節の配列を加工する予定です。
    例えば、節を示す行頭「◎」でさらにわけて、
    「◎」に「A1」、「A2」番号をふる、などを考えています。

    思いつきですが、配列ではなくハッシュの方がうまくいく気がしてきました。
    chapter_hash = Hash.new
    each.with_index(1) do |n, idx|
    chapter[idx] = n
    end

    >あと、質問の答では無いですが、上記の前半は1行でかけます。
    ありがとうございます。別の用途で短くしたかったので助かります。

    キャンセル

  • 2015/03/03 01:41

    >分割した後、さらに節別に配列を分け、節の配列を加工する予定です。
    同じように、slice_beforeで分割できると思うのですが、なにが問題と感じていますか?

    >each.with_index(1) do |n, idx|
    >chapter[idx] = n
    だと、配列と変わりませんね。スタートが0でなく1なだけで。

    キャンセル

  • 2015/03/03 13: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

    キャンセル

0

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

(やり方がまずいのかもしれません)
そうですね。
こんな感じでしょうか。
require "pp"
chapter_array = IO.readlines("scenario.txt").slice_before(/^■/).to_a
pp chapter_array
event_array = chapter_array.map do |chapter|
        chapter.slice_before(/^◎/).to_a
end
pp event_array
2次元配列のままですと幾重にも加工しようとするとごちゃごちゃになりそうなので、
2次元配列は、1次元配列の1次元配列なので、段階を踏んで考えればいです。

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

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

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

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

0

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

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

関連した質問

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