概要
個人的によく忘れるので、書き残しておきます。AtCoder のコードテストを使って調査します。
- 2020/06/19
- Python (3.8.2)
- numpy (1.18.2)
並び順:適当に思いついた順。なので、かなり適当順です。まぁ、自分用の覚え書きということで…。
1. for + print
import sys
import numpy as np
from time import perf_counter
A = np.random.randint(10**8, 10**9, 10**6, dtype=np.int32)
begin_time = perf_counter()
for x in A:
print(x)
end_time = perf_counter()
ms = int(1000 * (end_time - begin_time))
print(ms, file=sys.stderr)
コピペすれば、AtCoder のコードテスト環境で動くと思います。
$9$ 桁の 32 bit 整数 $10^6$ 個をランダムに生成します。これを標準出力に書き出したあと、出力部分にかかった時間を ms 単位で標準エラー出力に書き出します。
10回実行 → 676, 675, 687, 708, 657, 660, 734, 682, 665, 695
2. unpack + print
print(*A, sep='\n')
出力部分だけを差し替えます。
10回実行 → 567, 571, 582, 573, 571, 568, 572, 612, 566, 568
3. tolist + for + print
for x in A.tolist():
print(x)
10回実行 → 330, 335, 329, 324, 356, 328, 325, 328, 328, 328
トゥーリスト さんにリスト化してもらいます。numpy はベクトル計算の類は高速ですが、1 要素ずつ for ループを回すのは不得意だということが確認できます。
4. tolist + unpack + print
print(*A.tolist(), sep='\n')
10回実行 → 258, 262, 257, 256, 258, 260, 262, 258, 257, 261
5. numpy.savetxt
np.savetxt(sys.stdout, A, fmt='%d')
10回実行 → 1384, 1327, 1274, 1330, 1307, 1341, 1376, 1255, 1267, 1379
結構遅いんですね、知りませんでした。標準出力ではなくファイルに出力する場合も結構遅いみたいです。
6. numpy.array2string
S = np.array2string(A, separator='\n', threshold=10**6)
print(S[1:-1])
array を str に変換させてみます。項の数が閾値より多くなると [0 1 2 … 9997 9998 9998] のように両端だけ表示する string を作ります。閾値を大きく設定することで、全部の項をつないだ文字列になりそうです。
10000 ms 以上かかりました。こういう使い方は想定されていないのでしょう。
7. astype(str) + join
S = '\n'.join(A.astype(str))
print(S)
10回実行 → 773, 767, 771, 763, 780, 770, 760, 754, 795, 757
昔測定して、良い書き方だという記憶を持っていたけれど、私の記憶が嘘っぽいですね。(記憶じゃなくて記事化しておいた方が良いなという教訓)。
8. map(str) + join
S = '\n'.join(map(str, A))
print(S)
10回実行 → 521, 529, 564, 536, 701, 563, 572, 582, 590, 559
ひとつ外れ値っぽい結果が。
9. tolist + map(str) + join
S = '\n'.join(map(str, A.tolist()))
print(S)
iterate するときは tolist をかませた方が良いという教訓にならい。
10回実行 → 234, 221, 226, 223, 221, 223, 227, 222, 231, 231
まとめ
計測結果のグラフ可視化:さぼります。
S = '\n'.join(map(str, A.tolist()))
print(S)
これが一番早かった。np.ndarray は出力向けじゃないのかな。とりあえず list 化しておけば大きく損することはなさそう(そもそもこんなところが TLE を分けることはほとんどない)。
他の書き方を思いついた方:教えてくれるとうれしいです。