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

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

ただいまの
回答率

90.22%

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

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 733

tkche

score 3

 前提・実現したいこと

フォルダ内の特定の文字が入ったファイルに対して中身を処理し、処理した内容を書き込むというプログラムを作っています。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つのファイルに対して行ったプログラムは次の通りです。

f = open('test.txt',encoding="utf-8-sig")
data1 = f.read()  
f.close()

lines1 = data1.split('\n') 
print(lines1) 

i = 0
list1 = []
list2 = []

i = 0

for line in lines1:

    if i%3 == 0:
        list1.append(lines1[i]) 
    if i%3 == 1:
        list1.append(int(lines1[i]))        
    if i%3 == 2:
        list1.append(int(lines1[i])) 
        list2.append(list1)

        list1 = []
    i += 1
    print(line)
print(list2)

from operator import itemgetter

list2.sort(key=itemgetter(2))
print(format(list2))

f = open('narabikae.txt','w')

j = 0

for j in range(len(list2)):

    f.write(list2[j][0])
    f.write('\n')


f.close()

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

 該当のソースコード

ソースコード

 試したこと

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

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

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • tkche

    2018/04/15 19:09

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

    キャンセル

  • LouiS0616

    2018/04/15 19:11

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

    キャンセル

  • tkche

    2018/04/15 19:14

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

    キャンセル

回答 2

checkベストアンサー

+2

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

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 = data1.split('\n') 
    print(lines1) 

    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()

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

import os
data_dir = # 適切なデータディレクトリ名文字列("dirname/")
output_dir = # 適切な出力ディレクトリ名文字列("dirname/")

for data_filename in os.listdir(data_dir):
    mikan(data_dir + data_filename, output_dir + data_filename + ".narabikae.txt")

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/04/16 22:20

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

    キャンセル

  • 2018/04/16 22:46

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

    キャンセル

  • 2018/04/16 22:58

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

    キャンセル

+1

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

from operator import itemgetter
from pathlib import Path

def analyze_file(fin):
    lines = fin.readlines()

    if '"みかん"\n' not in lines[0::3]:
        return []

    data = [
        [f, int(key.strip('"\n'))] 
        for f, _, key in zip(*[iter(lines)]*3)
    ]
    return [elem[0] for elem in sorted(data, key=itemgetter(-1))]


parent_dir = Path(r'textがあるディレクトリ')
for filename in parent_dir.glob('text*.txt'):
    i = int(filename.name[4])  # 二桁以上の場合もあるならもうちょっと工夫が必要

    fin_path  = (parent_dir / f'text{i}.txt')
    fout_path = (parent_dir / f'narabikae{i}.txt')

    with fin_path.open() as fin:
        result = analyze_file(fin)

    if not result:
        continue

    with fout_path.open(mode='w') as fout:
        fout.writelines(result)

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

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