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

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

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

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

2回答

502閲覧

特定の文字が入ったファイルに対して中身の処理を行いたい。

tkche

総合スコア5

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2018/04/15 09:43

編集2018/04/15 10:08

前提・実現したいこと

フォルダ内の特定の文字が入ったファイルに対して中身を処理し、処理した内容を書き込むというプログラムを作っています。1つのファイルに対しては並び変えることができ、書き込みも成功したのですが、この前pythonを始めたばかりでfor文の使い方もあっているかわからず、複数ファイルに対して実行するプログラムをなかなか書くことができず苦戦しております。

例)
test1.txt
"りんご"
"120"
"10"
"ばなな"
"140"
"2"

test2.txt
"みかん"
"160"
"40"
"ぶどう"
"300"
"3"

というようなtxtファイルがあり、みかんが入っているファイルに対して
[["みかん","160","40"],["ぶどう","300","3"]]のように3行ごとにリストのリストに加え、各リストの3つ目の数字が小さい順に並び変えたものを作り、次のように書きこみたい。
narabikae.txt
"ぶどう"
"みかん"

1つのファイルに対して行ったプログラムは次の通りです。

python

1f = open('test.txt',encoding="utf-8-sig") 2data1 = f.read() 3f.close() 4 5lines1 = data1.split('\n') 6print(lines1) 7 8i = 0 9list1 = [] 10list2 = [] 11 12i = 0 13 14for line in lines1: 15 16 if i%3 == 0: 17 list1.append(lines1[i]) 18 if i%3 == 1: 19 list1.append(int(lines1[i])) 20 if i%3 == 2: 21 list1.append(int(lines1[i])) 22 list2.append(list1) 23 24 list1 = [] 25 i += 1 26 print(line) 27print(list2) 28 29from operator import itemgetter 30 31list2.sort(key=itemgetter(2)) 32print(format(list2)) 33 34f = open('narabikae.txt','w') 35 36j = 0 37 38for j in range(len(list2)): 39 40 f.write(list2[j][0]) 41 f.write('\n') 42 43 44f.close() 45 46

発生している問題・エラーメッセージ

該当のソースコード

ソースコード

試したこと

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

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

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

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

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

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

hayataka2049

2018/04/15 09:48

質問文を編集してコードブロックを適用してください
tkche

2018/04/15 10:02

お返事ありがとうございます。このサイトを使わせていただくのは初めてなのでうまく使い方が分かっておりません、コードブロックを適用とはどうすればよいのでしょうか。すみません。
LouiS0616

2018/04/15 10:04

『みかん』が一行目に書かれているとは限らず、四行目、七行目、... にある場合もあるのでしょうか。
tkche

2018/04/15 10:09

お返事ありがとうございます。例ではみかんは1行目に来ておりますが、内容が何十行にもなるファイルの処理も考えていますのでその場合もございます。
LouiS0616

2018/04/15 10:11

『みかん』がtext2.txt、text3.txtにあった場合、それぞれnarabikae2.txt、narabikae3.txtを作るのでしょうか。
tkche

2018/04/15 10:14

お返事ありがとうございます。はい、そのようなものを考えております。
guest

回答2

0

ベストアンサー

とりあえず、一つのファイルに対する処理を関数化します。記述を簡略化しましたが、処理内容はみかんが含まれていないファイルなら処理を中断するようにした以外は変えていません(私のミスがなければ)。まあ、これは参考にしてください。

python

1def mikan(input_filename, output_filename): 2 f = open(input_filename, encoding="utf-8-sig") 3 data1 = f.read() 4 f.close() 5 6 if "みかん" not in data1: 7 return 8 9 lines1 = data1.split('\n') 10 print(lines1) 11 12 result = [] 13 for i, line in enumerate(lines1): 14 if i%3 == 0: 15 tmp = [] 16 tmp.append(line) 17 if i%3 == 1: 18 tmp.append(int(line)) 19 if i%3 == 2: 20 tmp.append(int(line)) 21 result.append(tmp) 22 23 result.sort(key=lambda x:x[2]) 24 25 f = open(output_filename,'w') 26 for data in result: 27 f.write(data[0]) 28 f.write('\n') 29 f.close()

次に複数ファイルの取得方法ですが、os.listdirを使うとあるディレクトリ以下のファイル一覧が取れるので、さしあたってはこれを使えば良いでしょう。特定のディレクトリ(pythonファイルを置いたディレクトリに作ると簡単です)にデータをすべて放り込んでおきます。そのディレクトリとは別に、出力を保存するディレクトリも作っておきます。あとは下のような雰囲気でやれば良いでしょう(ファイル名などは適当です)。

python

1import os 2data_dir = # 適切なデータディレクトリ名文字列("dirname/") 3output_dir = # 適切な出力ディレクトリ名文字列("dirname/") 4 5for data_filename in os.listdir(data_dir): 6 mikan(data_dir + data_filename, output_dir + data_filename + ".narabikae.txt") 7

投稿2018/04/15 10:39

hayataka2049

総合スコア30933

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

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

tkche

2018/04/15 11:47

回答ありがとうございます、実行してみたところ UnicodeDecodeError: 'utf-8' codec can't decode byte 0x82 in position 1: invalid start byte とエラーが出たのですがファイルの読み込みの際にどのようなコードを加えればよいでしょうか。
hayataka2049

2018/04/15 11:54

エラーが出ている行はどこですか?
tkche

2018/04/15 12:12

該当箇所があっているか怪しいですが File "C:\Users\2017math1\Anaconda3\lib\encodings\utf_8_sig.py", line 69, in _buffer_decode return codecs.utf_8_decode(input, errors, final) というふうに出ています。
hayataka2049

2018/04/15 12:20

tracebackが出てると思うので、ぜんぶ貼ってください(ディレクトリ名などで個人情報が含まれていれば適宜伏せてくれて構いません)。それと、オリジナルのプログラムが実行できることをもう一度確認してください。
tkche

2018/04/15 12:30

オリジナルのほうを実行してみましたがそちらは実行できました。 File "<ipython-input-563-6ec6aa36de3a>", line 1, in <module> runfile('C:/Users/2017math1/Desktop/narabikae/narabikae1.py', wdir='C:/Users/2017math1/Desktop/narabikae') File "C:\Users\2017math1\Anaconda3\lib\site-packages\spyder\utils\site\sitecustomize.py", line 880, in runfile execfile(filename, namespace) File "C:\Users\2017math1\Anaconda3\lib\site-packages\spyder\utils\site\sitecustomize.py", line 102, in execfile exec(compile(f.read(), filename, 'exec'), namespace) File "C:/Users/2017math1/Desktop/narabikae/narabikae1.py", line 13, in <module> narabi(data_dir + data_filename, output_dir + data_filename + ".narabikae.txt") File "C:/Users/2017math1/Desktop/narabikae/koredeowarida2.py", line 10, in narabi output_dir = "C:/Users/2017math1/Desktop/narabikaego/" File "C:\Users\2017math1\Anaconda3\lib\codecs.py", line 321, in decode (result, consumed) = self._buffer_decode(data, self.errors, final) File "C:\Users\2017math1\Anaconda3\lib\encodings\utf_8_sig.py", line 69, in _buffer_decode return codecs.utf_8_decode(input, errors, final) UnicodeDecodeError: 'utf-8' codec can't decode byte 0x82 in position 1: invalid start byte になります。何度もすみません。
hayataka2049

2018/04/15 12:50

何回も確認させて申し訳ないのですが、使っているpythonのバージョンを確認してください。わからなければimport sys;print(sys.version)をコードの先頭に書いて確認できます。python3.xタグが付いていたのでpython3系を想定してプログラムを書きましたが、2系だとちょっと面倒なことになります。 次に、スクリプトファイルの文字コードを確認してください。基本的にはutf-8にしておくのが望ましいです。
tkche

2018/04/15 13:22

Anacondaのspyderというものを使っておりまして、python3.6と書かれているので3系ではあると思われます。文字コードはすべてutf-8で保存してあります。 一つのファイルに対して実行するほうはエラー無く動いたのですが、lines1になにも入っていないようでprintできない状態です。txtファイルがおかしいのでしょうか・・・
hayataka2049

2018/04/15 13:35

>printできない状態 これについて詳しく教えてください。正常にprintされないのですか?
tkche

2018/04/15 13:54

そのようです、エラーはないのですがprintされてません。回答していただいたコードの中で私が変更しなければいけない箇所はどこでしょうか。質問ばかりですみません。
hayataka2049

2018/04/15 13:57

確認ですが、「printされない」のは質問者様が質問文に貼ったコードですか? それとも私のコードを一つのファイルに対して実行した場合ですか? また、まったくprint結果が出ないという状況でよろしいですか?
tkche

2018/04/15 14:03

printされないのは回答していただいたコードです。
hayataka2049

2018/04/15 14:08

すみません、私のコードは入力データにみかんが含まれていないとprintされません・・・ 最初の f.close()のあとにprint(data1)を追加してください。 lines1 = data1.split('\n') print(lines1) も同じ位置に移動してしまって良いです。これでたぶん表示されるようになると思います。
tkche

2018/04/15 14:24

私が間違ってるかもしれないのですが、回答していただいたinput_filename や output_filenameを一番最初に input_filename = "text3.txt" output_filename = "narabikaego.txt"としたのですがこれはいいのでしょうか? これが原因でprintされないのかもしれないです。
hayataka2049

2018/04/15 14:30

関数の形で作りましたから、それらは引数に渡して呼び出してあげてください。 回答には示していませんが、次のように呼び出すことを想定しています。 mikan("text3.txt", "narabikaego.txt") これはdefブロックの外に書いてください。
tkche

2018/04/15 14:44

やはりprint結果が表示されないようです、、、 私に原因があるんでしょうけど、どこが悪いのかがわかりません。
hayataka2049

2018/04/15 14:45

とりあえずその分のコードは質問文に載せてみてください。私もそろそろ現状がよくわからなくなってきたので・・・
tkche

2018/04/15 15:04

input_filename = "text3.txt" output_filename = "narabikaego.txt" def mikan(input_filename, output_filename): f = open(input_filename, encoding="utf-8") data1 = f.read() f.close() print(data1) lines1 = data1.split('\n') print(lines1) if "みかん" not in data1: return result = [] for i, line in enumerate(lines1): if i%3 == 0: tmp = [] tmp.append(line) if i%3 == 1: tmp.append(int(line)) if i%3 == 2: tmp.append(int(line)) result.append(tmp) result.sort(key=lambda x:x[2]) f = open(output_filename,'w') for data in result: f.write(data[0]) f.write('\n') f.close() text3.txt "ぶどう" 1351699628 932 "みかん" 1351699719 1568 "イイネ" 1351699735 1276 "パイナップル" 1351700208 1696 "おいしい" 1351699318 808 です。
hayataka2049

2018/04/15 15:09

ソースコードの一番下の行に、インデントなしで mikan(input_filename , output_filename) を書いてください。とりあえず、これでこっちは動くはずです。
tkche

2018/04/15 15:31

ありがとうございます、こちらは無事動いてくれました;;
hayataka2049

2018/04/16 06:17

了解しました。文字コードの方は相変わらずよくわからないので、とりあえず処理を細かく分けてどこで落ちてるのかはっきりさせてみましょう。恐らく関数を呼び出す前だと思うので、文字列連結を関数呼び出しの外に持っていってみます。ついでに型を調べて変なことになっていないか確認します。 インデントを_で代用しています import os data_dir = # 適切なデータディレクトリ名文字列("dirname/") output_dir = # 適切な出力ディレクトリ名文字列("dirname/") print(type(data_dir), type(output_dir)) for data_filename in os.listdir(data_dir): ____input_filename = data_dir + data_filename ____output_filename = output_dir + data_filename + ".narabikae.txt" ____print(type(input_filename), type(output_filename)) ____mikan(input_filename, output_filename)
tkche

2018/04/16 11:01

ありがとうございます。実行しましたところ、型はすべてstrのようです。
hayataka2049

2018/04/16 11:40

この処理はどの段階でエラーを吐いて落ちますか?
tkche

2018/04/16 11:54

上のmikan(input_filename,output_filename)をインデントありで実行すると38行目に ValueError: invalid literal for int() with base 10: '"""' とエラーが出るようです。 インデントなしで実行すると出力ファイルに1つだけ書かれていました。
hayataka2049

2018/04/16 12:20

では、 for i, line in enumerate(lines1):の行の直下にインデントして次の記述を入れてください。 print(i, line) これでどこでエラーが出るか見てみよう、という作戦です。
hayataka2049

2018/04/16 12:21 編集

憶測ですがファイルの最後に複数入っている改行が空文字列を作ってしまった結果な気がするので、上に書いたprintをした結果それが裏付けられたのなら、 lines1 = data1.split('\n') の行を lines1 = [x for x in data1.split('\n') if x != ""] と書き換えてください。リストから空文字列を除去するコードです。
tkche

2018/04/16 12:42

回答者様のおっしゃる通り、最後の行に改行が含まれていました。 lines1を上記のように書き換えたのですが同じエラーが表示されました。
hayataka2049

2018/04/16 12:45

エラーが出るまでに入れたprintが何回か出力を出してると思うので、その結果をとりあえず貼ってみてください
tkche

2018/04/16 12:53

すごくごちゃごちゃしているのですが <class 'str'> <class 'str'> <class 'str'> <class 'str'> ['# -*- coding: utf-8 -*-', '"""', 'Created on Mon Apr 16 21:52:07 2018', '@author: 2017math1', '"""', 'import os', 'data_dir = "C:/Users/2017math1/Desktop/narabimae/"', 'output_dir = "C:/Users/2017math1/Desktop/narabikaego/"', 'print(type(data_dir), type(output_dir))', 'for data_filename in os.listdir(data_dir):', ' input_filename = data_dir + data_filename', ' output_filename = output_dir + data_filename + ".narabikae.txt"', ' print(type(input_filename), type(output_filename))', ' mikan(input_filename, output_filename)', 'def mikan(input_filename, output_filename):', ' f = open(input_filename, encoding="utf-8-sig")', ' data1 = f.read() ', ' f.close()', ' if "みかん" not in data1:', ' return ', ' lines1 = [x for x in data1.split(\'\n\') if x != ""]', ' print(lines1) ', ' result = []', ' for i, line in enumerate(lines1):', ' print(i,line)', ' if i%3 == 0:', ' tmp = []', ' tmp.append(line) ', ' if i%3 == 1:', ' tmp.append(int(line)) ', ' if i%3 == 2:', ' tmp.append(int(line)) ', ' result.append(tmp)', ' result.sort(key=lambda x:x[2])', " f = open(output_filename,'w')", ' for data in result:', ' f.write(data[0])', " f.write('\n')", ' f.close()'] 0 # -*- coding: utf-8 -*- 1 """ です
hayataka2049

2018/04/16 13:04

どうもソースコード(**.py)を入力として渡してしまっている気がします。ひょっとして対象データと**.pyが同階層にある? とりあえず、以下のディレクトリ構造に直してみてくださいな ..(省略)/Desktop/narabikae/ ┣narabikae.py(実行するスクリプト、名前は任意) ┣narabimae/(処理対象のデータ「のみ」入ったフォルダ) ┗narabikaego/ data_dir, output_dirは適切に変更しておいてください(.../Desktop/narabikae/narabimae/, ../Desktop/narabikae/narabikaego/とでもすれば良いです)
tkche

2018/04/16 13:20

無事動いてくれました! 本当に何から何までありがとうございますm(__)m お聞きしたいことがあるのですが、pythonやほかの言語はどのように習得されたのでしょうか? 最後までばかりですみません。
hayataka2049

2018/04/16 13:46

動くまでに一日以上かかっちゃいましたね。さくっと解決できなくて、こちらも申し訳なかったです。回答者として色々反省点があったので(ディレクトリの話とかしっかり説明しておくべきでした)、今後の教訓にさせていただきます プログラミングの習得の件は、私が答えると「学校の課題や研究で必要に迫られて覚えました」という面白みのない、参考にもならない話にしかなりません。別に質問立てて、色々な人から聞いてみたらどうです? 書き方が悪いと「問題・課題が含まれていない質問」とか低評価飛ばされちゃうかもしれないけど
tkche

2018/04/16 13:58

すみません、指摘がとても的確でどのように習得したのか興味があったものですから。 いろいろなところでまた聞いてみたいと思います。 今回は本当にありがとうございましたm(__)m
guest

0

pathlibを使うとこんな感じです。

Python

1from operator import itemgetter 2from pathlib import Path 3 4def analyze_file(fin): 5 lines = fin.readlines() 6 7 if '"みかん"\n' not in lines[0::3]: 8 return [] 9 10 data = [ 11 [f, int(key.strip('"\n'))] 12 for f, _, key in zip(*[iter(lines)]*3) 13 ] 14 return [elem[0] for elem in sorted(data, key=itemgetter(-1))] 15 16 17parent_dir = Path(r'textがあるディレクトリ') 18for filename in parent_dir.glob('text*.txt'): 19 i = int(filename.name[4]) # 二桁以上の場合もあるならもうちょっと工夫が必要 20 21 fin_path = (parent_dir / f'text{i}.txt') 22 fout_path = (parent_dir / f'narabikae{i}.txt') 23 24 with fin_path.open() as fin: 25 result = analyze_file(fin) 26 27 if not result: 28 continue 29 30 with fout_path.open(mode='w') as fout: 31 fout.writelines(result)

投稿2018/04/15 10:54

編集2018/04/15 10:59
LouiS0616

総合スコア35658

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問