#この記事について
python勉強中です。
csvモジュール縛りで色々やろうとしたところ、詰まってしまったので備忘録。
「pandas使えよ」って5回くらい思われるだろうなって感じですが、csvモジュール縛りに意味があるんだ!ということでやっておりました。はい。
いやその縛り意味あんのかよって言われると、そこは、もう、はい、すみません。
#やりたかったこと
csvモジュールしか使わない、という前提のもと、
既存のcsvファイルにカウントアップで上書きする。
csvファイルにはNAMEとCOUNTという列があり、
NAMEにはレストランの名前が、COUNTには数字が入る。
●CSVの例
NAME,COUNT
sukiya,1
matsuya,1
yoshinoya,2
#最初に書いたコード
import csv
fieldnames = ["NAME", "COUNT"]
# CSVファイルを読み取りで開く。また、行数を数えておく。
with open("csv_train.csv", "r", newline="") as csv_file:
reader = csv.DictReader(csv_file)
reader_list = list(reader)
rows_cnt = len(reader_list)
# CSVにデータがあれば、レコメンドを出す
if rows_cnt >= 1:
# 今何行目を読んでいるのかのカウント変数
t = 1
for row in reader_list:
print("My recommended retaurant is " + row["NAME"] + ".")
print("Do you like this restaurant? [Yes/No]")
ans = input()
# レコメンドに対してユーザーが「好き」と答えたら
if ans == "Yes":
with open("csv_train.csv", "w", newline="") as csv_file:
writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
writer.writeheader()
i = 1
for row in reader_list:
if i == t:
cnt = int(row["COUNT"]) + 1
writer.writerow({"NAME": row["NAME"], "COUNT": cnt})
else:
writer.writerow({"NAME": row["NAME"], "COUNT": row["COUNT"]})
i += 1
# レコメンドに対してユーザーが「好きではない」と答えたら
else:
pass
# カウント変数をカウントアップ
t += 1
# お礼を言ってクローズ
print("Have a good day!")
#何がしたいコードなのか
CSVモジュールを使ったデータの上書きについて、一行目から順番に更新していく、というやり方しか見当たらなかった(たぶん調べ方が悪いのだろう)。
なので、更新したい行数を指定してあげて、その行は更新するが、それ以外の行は元のデータの内容で上書き、という処理にした。
だいぶ頭の悪い処理だけど、他に思いつかなかった…
#何が起きるか?
データの最終行しかカウントアップされない。
#なぜか?
一番最初にcsvを読み込むときに、reader_listにcsvの中身を格納している。
また、書き込む際もreader_listに対してforを回して処理しようとしている。
だけど、このreader_listは最初に読み込んだ際のreader_listなので、
書き込み処理をする都度、一番最初のCSVの内容に戻ってしまう。
結果、一番最後の書き込み処理しか反映されないことになる。
#どうしたらいいのか?
書き込み処理をする都度、reader_listを更新してあげればよい。
import csv
fieldnames = ["NAME", "COUNT"]
# CSVファイルを読み取りで開く。また、行数を数えておく。
with open("csv_train.csv", "r", newline="") as csv_file:
reader = csv.DictReader(csv_file)
reader_list = list(reader)
rows_cnt = len(reader_list)
# CSVにデータがあれば、レコメンドを出す
if rows_cnt >= 1:
# 今何行目を読んでいるのかのカウント変数
t = 1
for row in reader_list:
print("My recommended retaurant is " + row["NAME"] + ".")
print("Do you like this restaurant? [Yes/No]")
ans = input()
# レコメンドに対してユーザーが「好き」と答えたら
if ans == "Yes":
#この処理を追加。書き込み前にreader_listを新しいのに変える。
with open("csv_train.csv", "r", newline="") as csv_file:
reader = csv.DictReader(csv_file)
reader_list = list(reader)
with open("csv_train.csv", "w", newline="") as csv_file:
writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
writer.writeheader()
i = 1
for row in reader_list:
if i == t:
cnt = int(row["COUNT"]) + 1
writer.writerow({"NAME": row["NAME"], "COUNT": cnt})
else:
writer.writerow({"NAME": row["NAME"], "COUNT": row["COUNT"]})
i += 1
# レコメンドに対してユーザーが「好きではない」と答えたら
else:
pass
# カウント変数をカウントアップ
t += 1
# お礼を言ってクローズ
print("Have a good day!")
#感想
CSVモジュールを使ったデータの更新処理が、ほんとにこういうやり方しかないのか?と思いながら書いてた。なんか無理やり解決した感がすごい。
「こういうの熟練の皆様はどういう風に書くのだろう」という興味で、コメントが貰えれば万々歳、スルーされてもやむなし、くらいの気持ちで、Qiita初投稿してみました。
初めて書いた記事がほんとにこれでいいのだろうか自分。あとで消したくなったりしないだろうか自分。どうだろうか自分。
なにはともあれ、最後まで読んでくださった方、有難うございました。