[numpy] numpy.ndarray の 標準出力

スポンサーリンク

概要

個人的によく忘れるので、書き残しておきます。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 を分けることはほとんどない)。

他の書き方を思いついた方:教えてくれるとうれしいです。

タイトルとURLをコピーしました