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

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

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

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

3回答

714閲覧

とある小説の文数を取得したい

daifuku-mochi

総合スコア9

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

1グッド

0クリップ

投稿2021/09/28 08:50

とある小説の文数を取得したいのですが、台詞の文数を正しく取得できずに困っております。
自身で下記のようなプログラムを書いてみたのですが、
「こんにちは。よろしくお願いします」
という台詞の場合、
「こんにちは。
よろしくお願いします」
と分けて出力されることに気づきました…

鍵括弧内の文にはreplace処理をしない、というような分岐はどのように書くことができますでしょうか?
もしくは別の書き方がありましたら是非教えていただけますと幸いです。

python

1#----- 別のファイルから文字を読み込む ----- 2 3#同ディレクトリのtxtファイルから文字列を取得する 4path = 'Novel.txt' 5file = open(path,'r',encoding='utf-8') 6original = file.read() 7 8#----- 文の数をかぞえる ----- 9 10#すべての『。』『」』『?』(全角)のうしろに「\n」(改行)を挿入する 11sentence = original.replace("。","。\n").replace("「","\n「").replace("?","?\n") 12#改行で区切りリスト化する 13list = sentence.split() 14x = 0 15for i in range(len(list)): 16 x = x + (len(list[i])) 17#合計数を全体数で割り、平均値を求める 18result = x / len(list) 19 20print('文数:' + str(len(list)))
SotaUN👍を押しています

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

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

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

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

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

ppaul

2021/09/28 09:48

彼は、「こんにちは。よろしくお願いします」と言いながら、こちらにやってきた。 は1文でいいですか? また、 彼は言った、「こんにちは。よろしくお願いします。」そして、こちらにやってきた。 は3文ですか2文ですか?
daifuku-mochi

2021/09/29 06:05 編集

確かに小説によっては鍵括弧と句点の組み合わせも存在しますね…盲点でした。 ご指摘いただきありがとうございます。 >彼は、「こんにちは。よろしくお願いします」と言いながら、こちらにやってきた。の場合、 彼は、 「こんにちは。よろしくお願いします」 と言いながら、こちらにやってきた。 のように3文に分けたいです。 >彼は言った、「こんにちは。よろしくお願いします。」そして、こちらにやってきた。の場合、 彼は言った、 「こんにちは。よろしくお願いします。」 そして、こちらにやってきた。 のように3文に分けたいです。 ※誤りがありましたので29日の15時ごろ一部訂正しました。
guest

回答3

0

txt = "彼は、「こんにちは。よろしくお願いします」と言いながら、こちらにやってきた。彼は言った、「こんにちは。よろしくお願いします。」そして、こちらにやってきた。" txts = re.split(r'(「.*?」)', txt) i=0 for x in txts: i+=1 print(i, x)

こんな感じに正規表現でsplitすると

1 彼は、 2 「こんにちは。よろしくお願いします」 3 と言いながら、こちらにやってきた。彼は言った、 4 「こんにちは。よろしくお願いします。」 5 そして、こちらにやってきた。

このように、地の文、台詞、地の文、台詞……のように分割できるので、それぞれで適切な処理を施せばいいんじゃないでしょうか。

投稿2021/09/28 11:37

KojiDoi

総合スコア13671

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

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

ppaul

2021/09/28 22:29 編集

>>> txt = 'きのう、「彼は、「こんにちは。よろしくお願いします」と言った」と書いてある手紙が来た。' >>> txts = re.split(r'(「.*?」)', txt) >>> i=0 >>> for x in txts: ... i+=1 ... print(i, x) ... 1 きのう、 2 「彼は、「こんにちは。よろしくお願いします」 3 と言った」と書いてある手紙が来た。 となってしまいますね。
KojiDoi

2021/09/29 03:19

入れ子には確かにうまく対応できないですね。というか、ただしく開閉の括弧が対応している保証もないといえばないので、そうした事態を懸念するなら何か前処理が要ります。しかし、まともなところが出している文章であれば、こういうカギカッコの使い方はあり得ないのも確かです(中のカッコは『』になる)。 現実にどのようなデータを相手にするかですね。
daifuku-mochi

2021/09/29 04:47

>KojiDoi様 ご回答いただきありがとうございます。 あまり正規表現に詳しくなかったので、raw stringなど勉強になりました。 用途の説明が足りておらず申し訳ないのですが、台詞に限らず小説全体の文数を取得したいので、 できれば台詞以外の文章は句点区切りの文単位で取得したいです。 1 彼は、 2 「こんにちは。よろしくお願いします」 3 と言いながら、こちらにやってきた。 4 彼は言った、 5 「こんにちは。よろしくお願いします。」 6 そして、こちらにやってきた。
KojiDoi

2021/09/29 05:48

ええ、ですから「セリフ以外の文章」は別途処理を続ける前提のコードですよ。完成品ではありません。
daifuku-mochi

2021/09/29 06:05 編集

意図を汲み取れず申し訳ありませんでした。どうすれば加工して文数を取り出せるかもう少し考えてみます。
guest

0

ベストアンサー

replace処理をするよりは少し面倒になってしまいますが、

文字列originalを前から1文字ずつ見ていき、カギ括弧の中か外かをフラグで管理しておいた上で、カギ括弧の外にいる場合のみ、文末を示す記号の所で文の数のカウントを増やす

というのはどうでしょうか。

投稿2021/09/28 09:02

SotaUN

総合スコア17

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

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

daifuku-mochi

2021/09/29 05:56 編集

フラグを使う方法は思いつきませんでしたので教えていただき大変有難かったです。 SotaUN様の案を参考に書いてみました。 original = "彼はこう言った、「よろしくお願いします」さわやかな笑顔だった。" lineTotal = 0 sentenceTotal = 0 lineFlag = False for x in original: #"「"の場合、フラグをTrueにする if x == "「": lineFlag = True #"」"の場合、フラグをFalseにする elif x == "」": lineFlag = False #台詞のカウントに1足す lineTotal = lineTotal + 1 #フラグがFalseの場合、値が"。"または"?"の場合 if lineFlag == False and x == "。" or x == "?": #文のカウントに1足す sentenceTotal = sentenceTotal + 1 print(lineTotal) print(sentenceTotal) ただ、"「"の前が読点で終わるような文を台詞文と分けて取得する方法を 思いつくことができませんでした…
SotaUN

2021/09/29 06:41

for x in original:ではなく for i in range(len(original)):のようにすれば、 #"、”の場合、次の文字が”「”なら if original[i] == “、”: if original[i+1] == “「”: #文のカウントに1足す sentenceTotal = sentenceTotal + 1 のような感じで数えられるのではないでしょうか。
daifuku-mochi

2021/09/29 08:57

ご返答いただきありがとうございます。 lineTotal = 0 sentenceTotal = 0 lineFlag = False for i in range(len(original)): #"「"の場合、フラグをTrueにする if original[i] == "「": lineFlag = True #"」"の場合、フラグをFalseにする elif original[i] == "」": lineFlag = False #台詞のカウントに1足す lineTotal = lineTotal + 1 #フラグがFalseの場合、 if lineFlag == False: #値が"。"または"?"の場合 if original[i] == "。" or original[i] == "?": #文の合計カウントに1を足す sentenceTotal = sentenceTotal + 1 #鍵括弧の前が句点で終了していない場合、 if original[i] == "「": if original[i-1] != "。": #文の合計カウントに1を足す sentenceTotal = sentenceTotal + 1 print(lineTotal) print(sentenceTotal) 以上で取り出すことができました!本当にありがとうございました…!
guest

0

カッコ内を1文とする、ってことなら、最初にカッコに囲まれる文章を1文に認識されるように置換してしまい、それから処理を行えばいいのではないかと。

投稿2021/09/28 08:57

y_waiwai

総合スコア87782

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問