書いてあること
- 二次元配列の入力の受け取り方
- リストの内包表記
記事執筆の経緯
こんな入力を受け取りたいのですが…
H W
A11 A12 ... A1W
A21 A22 ... A2W
AH1 AH2 ... AHW
「え、どうすればいいの??」
とやり方をど忘れしたので、備忘録がてら記事を書くことにしました。
環境
Python(3.8.2)
※実行速度のこと考えるならPyPy3の方がいいです、多分動きます。
⇒PyPy3(7.3.0)でも動きました
本題のコード
H, W = map(int, input().split())
A = [[int(x) for x in input().split()] for i in range(H)]
リストの内包表記とは
簡潔に言えば、for文を使って配列を生成する方法です。
以下のように使えます。
[式 for 任意の変数名 in イテラブルオブジェクト]
(note.nkmk.meさんからの引用です、いつもお世話になっております)
- 式
- int()とか、この式の出力結果がそのまま配列の要素となる
- 任意の変数名
- iとかkとか、イテラブルオブジェクトの中身が一つずつ順番に入る
- イテラブルオブジェクト
- 配列とかrange関数とか、for文で回せるやつ
x = [i*3 for i in range(10)]
print(x)
>>> [0, 3, 6, 9, 12, 15, 18, 21, 24, 27]
# 0-9までの要素を一つずつiに取り出し、i*3に入れている
# i*3の結果を一つずつ新たに生成する配列の要素として格納している
# 以下の入力を受け取りたい
# 1 2 3 4 5 6 7 8 9 10
A = [int(x) for x in input().split()]
print(A)
>>> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# 入力を空白区切りでイテラブルオブジェクトとして取得
# それを一つずつint()に渡し、
# その出力結果(int型にキャスト)を新たに生成する配列の要素として格納している
見た目難しそうなのに結構中身単純ですね。
本題のコードの解説
内包表記がネストになっていて少し複雑ですが、ネスト外側の内包表記から見ていくと理解しやすいかも。以下、コード再掲。
H, W = map(int, input().split())
A = [[int(x) for x in input().split()] for i in range(H)]
外側の内包表記の意味
A = [[内側の省略] for i in range(H)]
range(H)を式[内側の省略]に入れて繰り返すよって意味。でも、式[内側の省略]にはiが使われていないため、式[内側の省略]をただただH回繰り返すよって意味になっている。
内側の内包表記の意味
A = [[int(x) for x in input().split()] 外側の省略]
リストの内包表記を解説したところで出したex2.pyと同じ意味。
一行の空白区切りの入力を受け取って、それを配列化する。
本題のコードの動き
外側のfor i in range(H)のiが一つ進む度に読み込む入力の行が一つ進み、
入力を一行もらっては一次元の配列にし、それを二次元配列の要素として組み込む。
終わりに
誰かの参考にしてもらおうと言うより、自分自身のメモとして自己満足のために書いた記事です。ミスがあってもスルーしていただくか、お手柔らかにご指摘をしていただけると幸いです。