LoginSignup
0
1

More than 3 years have passed since last update.

Python未経験者が言語処理100本ノックをやってみる10~13

Last updated at Posted at 2020-03-19

今日から第2章。
これの続きでーす。
Python未経験者が言語処理100本ノックをやってみる07~09
https://qiita.com/earlgrey914/items/a7b6781037bc0844744b

第1章で「7時間かかった」と言ったら「仕事は?」と言われました。
もちろんしてますeん。


下準備

hightemp.txtは,日本の最高気温の記録を「都道府県」「地点」「℃」「日」のタブ区切り形式で格納したファイルである.以下の処理を行うプログラムを作成し,hightemp.txtを入力ファイルとして実行せよ.さらに,同様の処理をUNIXコマンドでも実行し,プログラムの実行結果を確認せよ.

このhightemp.txtを入力ファイルとして
・処理を行うPythonプログラムを書く
・UNIXコマンドでも同様の処理(コマンド実行)をしてみる
ってのが第2章の内容みたいです。

hightemp.txtの中身はこんな感じ。
タブ区切りの24行4列のデータ。

hightemp.txt
高知県   江川崎   41  2013-08-12
埼玉県   熊谷  40.9    2007-08-16
岐阜県   多治見   40.9    2007-08-16
山形県   山形  40.8    1933-07-25
山梨県   甲府  40.7    2013-08-10
和歌山県    かつらぎ    40.6    1994-08-08
静岡県   天竜  40.6    1994-08-04
山梨県   勝沼  40.5    2013-08-10
埼玉県   越谷  40.4    2007-08-16
群馬県   館林  40.3    2007-08-16
群馬県   上里見   40.3    1998-07-04
愛知県   愛西  40.3    1994-08-05
千葉県   牛久  40.2    2004-07-20
静岡県   佐久間   40.2    2001-07-24
愛媛県   宇和島   40.2    1927-07-22
山形県   酒田  40.1    1978-08-03
岐阜県   美濃  40  2007-08-16
群馬県   前橋  40  2001-07-24
千葉県   茂原  39.9    2013-08-11
埼玉県   鳩山  39.9    1997-07-05
大阪府   豊中  39.9    1994-08-08
山梨県   大月  39.9    1990-07-19
山形県   鶴岡  39.9    1978-08-03
愛知県   名古屋   39.9    1942-08-02

私はPython実行環境としてAWS Cloud9を利用していますので、
そちらに本txtファイルをアップしてから開始です。

余談ですけど、Cloud9は本当に便利ですね。
Cloud9でネイティブGUIアプリの開発もできると嬉しいなぁと思ってます(おかしな事を言っている)

10. 行数のカウント

行数をカウントせよ.確認にはwcコマンドを用いよ.

えーと。まずPythonでtxtファイルを読み込む方法っと。
これは知ってる。.pyと同じところに.txtを置いてるからこれで大丈夫でしょう。

yomikoku.py
with open('hightemp.txt') as f:
    s = f.read()
    print(s)
Traceback (most recent call last):
  File "/home/ec2-user/knock/02/enshu11.py", line 6, in <module>
    with open('hightemp.txt') as f:
FileNotFoundError: [Errno 2] No such file or directory: 'hightemp.txt'

あらー。ダメなのね。

~3分ほどググる~

<参考URL>
https://qiita.com/nagamee/items/b7d1b02074293fdfdfff

korede.py
import os.path

#このpyファイルのある場所を原点とする
os.chdir((os.path.dirname(os.path.abspath(__file__))))

with open('hightemp.txt') as f:
    s = f.read()
    print(s)
高知県  江川崎  41      2013-08-12
埼玉県  熊谷    40.9    2007-08-16
:

これでOK。
このos.chdir((os.path.dirname(os.path.abspath(__file__))))のおまじない?は今後も書いていっていいものなのだろうか?
実行環境によって必要だったり不要(というか書いてはダメ)だったりしそう・・・

で、ファイルをopen()したあとにどういった形で中身を読み込むかはいくつかやり方があるようだ。
今回の問題では「行数をカウントせよ」とのことなので、行単位でリストにしてくれるreadlines()を使うのがいいだろう。

enshu10.py
import os.path

#このpyファイルのある場所を原点とする
os.chdir((os.path.dirname(os.path.abspath(__file__))))

with open('hightemp.txt') as f:
    s = f.readlines()
    print(len(s))
24

簡単でござる。
UNIXコマンドでも同じことをしろとのことなので実行。

[ec2-user@ip-172-31-34-215 02]$ wc -l hightemp.txt 
24 hightemp.txt

ファイル名が邪魔だな。
catをかまそう。

[ec2-user@ip-172-31-34-215 02]$ cat hightemp.txt | wc -l
24

11. タブをスペースに置換

タブ1文字につきスペース1文字に置換せよ.確認にはsedコマンド,trコマンド,もしくはexpandコマンドを用いよ.

なんか1章より簡単じゃない?

eunshu11.py
import os.path

os.chdir((os.path.dirname(os.path.abspath(__file__))))

with open('hightemp.txt', mode="r") as f:
    s = f.read()
    tikango = s.replace("\t", " ") 

with open('hightemp.txt', mode="w") as f:
    f.write(tikango)
hightemp.txt
高知県 江川崎 41 2013-08-12
埼玉県 熊谷 40.9 2007-08-16
岐阜県 多治見 40.9 2007-08-16
山形県 山形 40.8 1933-07-25
山梨県 甲府 40.7 2013-08-10
和歌山県 かつらぎ 40.6 1994-08-08
静岡県 天竜 40.6 1994-08-04
山梨県 勝沼 40.5 2013-08-10
埼玉県 越谷 40.4 2007-08-16
群馬県 館林 40.3 2007-08-16
群馬県 上里見 40.3 1998-07-04
愛知県 愛西 40.3 1994-08-05
千葉県 牛久 40.2 2004-07-20
静岡県 佐久間 40.2 2001-07-24
愛媛県 宇和島 40.2 1927-07-22
山形県 酒田 40.1 1978-08-03
岐阜県 美濃 40 2007-08-16
群馬県 前橋 40 2001-07-24
千葉県 茂原 39.9 2013-08-11
埼玉県 鳩山 39.9 1997-07-05
大阪府 豊中 39.9 1994-08-08
山梨県 大月 39.9 1990-07-19
山形県 鶴岡 39.9 1978-08-03
愛知県 名古屋 39.9 1942-08-02

ターミナルでもsedで置換してみる。

[ec2-user@ip-172-31-34-215 02]$ sed -i -e "s/\t/ /g" hightemp.txt
[ec2-user@ip-172-31-34-215 02]$ cat hightemp.txt 
高知県 江川崎 41 2013-08-12
埼玉県 熊谷 40.9 2007-08-16
岐阜県 多治見 40.9 2007-08-16
山形県 山形 40.8 1933-07-25
山梨県 甲府 40.7 2013-08-10
和歌山県 かつらぎ 40.6 1994-08-08
静岡県 天竜 40.6 1994-08-04
山梨県 勝沼 40.5 2013-08-10
埼玉県 越谷 40.4 2007-08-16
群馬県 館林 40.3 2007-08-16
群馬県 上里見 40.3 1998-07-04
愛知県 愛西 40.3 1994-08-05
千葉県 牛久 40.2 2004-07-20
静岡県 佐久間 40.2 2001-07-24
愛媛県 宇和島 40.2 1927-07-22
山形県 酒田 40.1 1978-08-03
岐阜県 美濃 40 2007-08-16
群馬県 前橋 40 2001-07-24
千葉県 茂原 39.9 2013-08-11
埼玉県 鳩山 39.9 1997-07-05
大阪府 豊中 39.9 1994-08-08
山梨県 大月 39.9 1990-07-19
山形県 鶴岡 39.9 1978-08-03
愛知県 名古屋 39.9 1942-08-0

12. 1列目をcol1.txtに,2列目をcol2.txtに保存

各行の1列目だけを抜き出したものをcol1.txtに,2列目だけを抜き出したものをcol2.txtとしてファイルに保存せよ.確認にはcutコマンドを用いよ.

なんか一気に簡単になってしまいやる気減。

enshu12.py
import os.path

os.chdir((os.path.dirname(os.path.abspath(__file__))))

with open('hightemp.txt', mode="r") as f:
    linedata = f.readlines()
    for l in linedata:
        with open('col1.txt', mode="a") as c1:
            c1.write(l.split(" ")[0] + "\r")
        with open('col2.txt', mode="a") as c2:
            c2.write(l.split(" ")[1] +"\r")
col1.txt
高知県
埼玉県
岐阜県
山形県
山梨県
和歌山県
静岡県
山梨県
埼玉県
群馬県
群馬県
愛知県
千葉県
静岡県
愛媛県
山形県
岐阜県
群馬県
千葉県
埼玉県
大阪府
山梨県
山形県
愛知県

col2.txt
江川崎
熊谷
多治見
山形
甲府
かつらぎ
天竜
勝沼
越谷
館林
上里見
愛西
牛久
佐久間
宇和島
酒田
美濃
前橋
茂原
鳩山
豊中
大月
鶴岡
名古屋

cutコマンドはこうでしょ。

[ec2-user@ip-172-31-34-215 02]$ cut -f 1 -d " " hightemp.txt > col1_command.txt 
[ec2-user@ip-172-31-34-215 02]$ cut -f 2 -d " " hightemp.txt > col2_command.txt

diffで比較っと・・・

[ec2-user@ip-172-31-34-215 02]$ diff col1.txt col1_command.txt 
1c1,24
愛知県県
\ No newline at end of file
---
> 高知県
> 埼玉県
> 岐阜県
> 山形県
> 山梨県
> 和歌山県
> 静岡県
> 山梨県
> 埼玉県
> 群馬県
> 群馬県
> 愛知県
> 千葉県
> 静岡県
> 愛媛県
> 山形県
> 岐阜県
> 群馬県
> 千葉県
> 埼玉県
> 大阪府
> 山梨県
> 山形県
> 愛知県

アレッ!?
cat col1.txtでも表示されないからこれは・・・
改行コードのせいだ!
ということで改行コードを\rから\nに変え、ファイル書き込み時のエンコードもUTF-8を指定しました。

enshu13.py
import os.path

os.chdir((os.path.dirname(os.path.abspath(__file__))))

with open('hightemp.txt', mode="r") as f:
    linedata = f.readlines()
    for l in linedata:
        with open('col1.txt', mode="a", encoding="utf-8") as c1:
            c1.write(l.split(" ")[0] + "\n")
        with open('col2.txt', mode="a", encoding="utf-8") as c2:
            c2.write(l.split(" ")[1] +"\n")

実行確認

[ec2-user@ip-172-31-34-215 02]$ python3 enshu12.py
[ec2-user@ip-172-31-34-215 02]$ 
[ec2-user@ip-172-31-34-215 02]$ cut -f 1 -d " " hightemp.txt > col1_command.txt
[ec2-user@ip-172-31-34-215 02]$ cut -f 2 -d " " hightemp.txt > col2_command.txt
[ec2-user@ip-172-31-34-215 02]$ diff col1.txt col1_command.txt
[ec2-user@ip-172-31-34-215 02]$ diff col2.txt col2_command.txt
[ec2-user@ip-172-31-34-215 02]$ 

おっけーでーす。

13. col1.txtとcol2.txtをマージ

12で作ったcol1.txtとcol2.txtを結合し,元のファイルの1列目と2列目をタブ区切りで並べたテキストファイルを作成せよ.確認にはpasteコマンドを用いよ.

たぶんこんな感じでいけるけど、もっといいやり方ないかしら?

tabun.py

with open col1.txt
     すべての行を配列1に入れる

with open col2.txt
     すべての行を配列2に入れる

for[i]
    出力ファイル = write(配列1[i] + "\t" + 配列2[i])

~20分後~

enshu13.py
import os.path

os.chdir((os.path.dirname(os.path.abspath(__file__))))

linedata_col1 = []
linedata_col2 = []

with open('col1.txt', mode="r") as f:
    linedata_col1 = f.read().splitlines()


with open('col2.txt', mode="r") as f:
    linedata_col2 = f.read().splitlines()

with open('merge.txt', mode="a", encoding="utf-8") as f:
    for c1, c2 in zip(linedata_col1, linedata_col2):
        f.write(c1 + "\t" + c2 + "\n")
merge.txt
高知県   江川崎
埼玉県   熊谷
岐阜県   多治見
山形県   山形
山梨県   甲府
和歌山県    かつらぎ
静岡県   天竜
山梨県   勝沼
埼玉県   越谷
群馬県   館林
群馬県   上里見
愛知県   愛西
千葉県   牛久
静岡県   佐久間
愛媛県   宇和島
山形県   酒田
岐阜県   美濃
群馬県   前橋
千葉県   茂原
埼玉県   鳩山
大阪府   豊中
山梨県   大月
山形県   鶴岡
愛知県   名古屋

工夫ポイントはlinedata_col1 = f.read().splitlines()です。
f.readlines()で1行ずつ読み込むのもアリなんだけど、それだと↓のように改行コード込みのリストになってしまいます。

readlinesdato.py
with open('col1.txt', mode="r") as f:
    linedata_col1 = f.readlines()
    print(linedata_col1)
['高知県\n', '埼玉県\n', '岐阜県\n', '山形県\n', '山梨県\n', '和歌山県\n', '静岡県\n', '山梨県\n', '埼玉県\n', '群馬県\n', '群馬県\n', '愛知県\n', '千葉県\n', '静岡県\n', '愛媛県\n', '山形県\n', '岐阜県\n', '群馬県\n', '千葉県\n', '埼玉県\n', '大阪府\n', '山梨県\n', '山形県\n', '愛知県\n']

この改行コードをわざわざ消すくらいなら、read()で改行コード込みでブロックオブジェクトとして読み込み、改行コードでsplit()してリスト化するのがベストだと思いました。

ではpasteとの比較。

[ec2-user@ip-172-31-34-215 02]$ python3 enshu13.py
[ec2-user@ip-172-31-34-215 02]$ paste col1.txt col2.txt > merge_command.txt
[ec2-user@ip-172-31-34-215 02]$ diff merge.txt merge_command.txt 
[ec2-user@ip-172-31-34-215 02]$ 

なんだか簡単かつ、ファイルを挟むので結果検証が面倒になってきたぞ。
続きは明日にしよ~かな~
ここまで2時間かかりました!!ダラダラやってなので今回はあまり参考にならないかと。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1