はじめに
本稿は、自分用に備忘録としてmapオブジェクトの取り扱いの失敗例を載せていきます。
それと同時に、標準入力でよく併用されるリスト内包表記についても軽く触れていきます。
(筆者は、記事を書き始めた当初、リスト内包表記の挙動がおかしいと勘違いしていた。)
特に丁寧な説明とかはないので、悪しからず。
実行環境:python 3.11.4
リスト内包表記のメリット
主に標準入力で使用する為、for文との比較になる。
①計算量が少ない。つまり、速い。
※.append()の実行速度が遅すぎる。yield文使えば良くね???
②コードがシンプルになる。
シンプルイスザベスト。
使用例0(失敗例)
n = int(input())
li = [map(int, input().split()) for i in range(n)]
#出力1
print(li)
#出力2
print(list(li))
#出力3
print(*li)
#priny
n行m列の標準入力データの受け取りである。
気をつけて欲しいのだが、liの出力が全てmapオブジェクトになってしまう。
リスト内包表記の中で、map関数で直接受け取ったオブジェクトは、
何故かリスト型への変換も*によるアンパックもできないみたいである。
と、筆者は勘違いしていた。
入出力例
入力データ
2
5 3 4
7 9 11
出力
[<map object at 0x104fbace0>, <map object at 0x104fbac80>]
[<map object at 0x104fbace0>, <map object at 0x104fbac80>]
<map object at 0x104fbace0> <map object at 0x104fbac80>
実は出力例2を、print(list(li[0]),list(li[1]))とすると、普通に出力される。
要は上記のコードでは、listオブジェクトであるliをリスト化したり、アンパックしていたのである。
つまり、liはlistオブジェクトで、liの要素がmapオブジェクトだった為に、mapオブジェクトが出力される事態に至っていたのである。
list(map(int, ......)) ← これ本当に大事。
皆様は、mapオブジェクトのリスト化をゆめゆめ忘れないように……
修正例
n = int(input())
li = [list(map(int, input().split())) for i in range(n)]
print(li)
n行m列のデータの受け取り。上記の入力例から試してみると良い。
リスト内包表記?
n = int(input())
E = [0 for i in range(n)]
print(E)
1行n列の0ベクトルの生成。
変な利用方法だが、便利そうなので忘れたくない。
ABC081Bの解答例
n = int(input())
li = list(map(int, input().split()))
E = [0 for i in range(n)]
cnt=0
while True:
#「liの要素のmod2と、Eの要素が等しいか」を判定。
if list(map(lambda x: x%2, li)) != E:
break
cnt+=1
li = list(map(lambda x:x/2, li))
print(cnt)
0ベクトルの利用例
ABC081Bを参照。
受け取った標準入力をmap関数とラムダ式を用いて、リストの全要素が2で割り切れるかを判定するコード。
要は0リスト(0ベクトル)と渡されたリストの比較をしたかったのである。
その為、ラムダ式でリストの要素に作用させた。
着想はベクトルの一意性の利用。
入力データ①
3
8 12 40
出力は2
入力データ②
6
382253568 723152896 37802240 379425024 404894720 471526144
出力は8
後書き
以上、mapオブジェクトに二時間発狂し続けた悲しき男の備忘録でした〜
二重ループ回すより、綺麗に処理できてスッキリ!!!
参考になったら、幸いです。