小ネタです。
AtCoderやPaizaなど、Web上のプログラミングテストみたいなものを受けるとき、
標準入力に半角スペース区切りで入力が渡される
みたいな場合が多いです。そのときに1行で標準入力を展開する方法を書いてみます。
例題
半角スペース区切りで
N M
S-1
S-2
…
S-n
という形式で入力が渡される。N
とM
は数値とする。
S
は文字列で、N
の数値回数分だけ渡される。
M
は、問題のどこかで使う値ということにしましょう。この記事では使いません。
入力を受け取る
n, m = (int(x) for x in input().split())
これでいけます。
さらに、S
も受け取るなら
n, m = (int(x) for x in input().split())
for i in range(n):
s = input()
# 問題を解く
という感じで受け取れます。
解説
処理は、以下の順で行われています。
input関数
input()
は、入力から1行取り、文字列で返します。改行は含まれません。
上記の問題だと、
N M
という、半角スペースで区切られた文字列を返してきます。
split関数
文字列を、引数で指定した文字があるところで分割したlist
を返します。
引数を指定しないと、だいたい半角スペースで区切ってくれます。よって、今回のケースだと引数を指定する必要がありません。
参考:https://docs.python.org/ja/3/library/stdtypes.html#str.split
内包表記
(int(x) for x in input().split())
というような、(... for ... in list)
みたいな表記を、内包表記といいます。
あえて別のソースで書くなら、
```python`
str_list = input().split()
for x in str_list:
yield int(x)
という処理に近いです。`x`に、元のリスト内の要素(今回だと文字列が渡されているので、個々の文字を示す文字列)が入ってきます。
`[... for ... in list]`と、`[]`で括るとリストが返ってきて、`()`で括るとタプルが返ってきます。
### キャスト
上で書いたように、内包表記で個々の文字が文字列で返ってくるので、それをそのまま`int`に型変換しています。
`int(x)`みたいに数値に変換したい値を渡すと、いい感じに数値に変換してくれます。
### タプル、リストのアンパック
公式ドキュメントの以下のページに記載があります。
https://docs.python.org/ja/3/tutorial/datastructures.html#tuples-and-sequences
例えば、要素数が2のタプル(変数`t`)があったとすると、
```python
a, b = t
と書くと、ループやインデックスでのアクセスを行わなくても中身を展開して取り出せます。上記の書き方で、要素数が2ではない場合、エラーが発生します。(画像はVisual Studio Codeのもの)
要素数が決まっていない場合は扱えませんが、競技プログラミングのように、どのような入力が渡ってくるか決まっている場合は問題なく使えます。
余談ですが、アンパックはタプルでもリストでも可能です。どちらもSequence
だからです。
解説まとめ
1行で書かれていた標準入力を展開する処理ですが、処理は以下の順で行われています。
- 標準入力をそのまま受け取る
- 半角スペースで区切ってリストにする
- リストの中身を内包表記の中で数値に変換する
- 内包表記をアンパックして変数に格納
おわりに
今回のコードは、定型文として覚えておくとそのまま使えますが、仕組みを知っておくと応用が利きます。
特に内包表記はPythonで多用する(というより使わざるを得ない場合が多い)ので、慣れておくとできることが増えて楽しいです。