0
2

More than 3 years have passed since last update.

Pythonの内包表記が好きなのでmapと比較検証してみた

Posted at

はじめに

 こんにちは、麻菜結です。Pythonの内包表記が数多あるプログラミング言語の記法の中でも多機能かつ可読性が高く素晴らしい文法なのは間違いありませんが(個人の意見であり多大に偏見を含んでいる可能性があります)、よく競技プログラミングでは以下の記法が見られます。

l = list(map(int, input().split()))

 内包表記の敵、mapですね(偏見を(略)。いちいちlistかまさないといけないmapがなんぼのもんじゃい!ということで速度を比較してみました。

環境

wsl1のUbuntuを使います。

$ uname -a
Linux LAPTOP-H6KC5C7N 4.4.0-18362-Microsoft #1049-Microsoft Thu Aug 14 12:01:00 PST 2020 x86_64 x86_64 x86_64 GNU/Linux
$ py --version
Python 3.8.0

概要

1 10000行5列の非負な整数値が並ぶテキストファイルを用意する。先頭に10000と記述しファイルの列の数とする。
2 timeモジュールのtime()を用いて始まりの時間を記録する。
3 行ごとに内包表記かmapでデータを格納する。
4 data.appendを繰り返して終わったらtime()で時間を取得して2の値と差分を出しそれを実行時間として表示する。
5 5回ほど試しそれの平均を取り比較する。

スクリプト

以下のスクリプトを用います。

内包表記
import time

start = time.time()
n = int(input())
data = []
for _ in range(n):
    data.append([int(e) for e in input().split(" ")])
process_time = time.time() - start

print(process_time)
map
import time

start = time.time()
n = int(input())
data = []
for _ in range(n):
    data.append(list(map(int, input().split())))
process_time = time.time() - start

print(process_time)

検証

五回ぐらい実行してみてその平均を考えてみます。
まずは内包表記です。まぁまずまずですね。

内包表記
$ for((i=0;i<5;i++)); do cat InputText.txt | py time_comp.py; done
0.0833895206451416
0.07289266586303711
0.08693099021911621
0.12533855438232422
0.09039974212646484

平均すると0.09541くらいでしょうか。
次にmapです。

map
$ for((i=0;i<5;i++)); do cat InputText.txt | py time_map.py; done
0.0980367660522461
0.08674144744873047
0.11994338035583496
0.08462047576904297
0.08770060539245605

こちらも平均すると0.09541と同じですね。
(いや有意差が無いぞ…内包表記遅いやないかい!で記事書こうと思ったのに)

追加検証

ラズパイ4でやりました。

$ uname -a
Linux asana 5.4.51-v8+ #1333 SMP PREEMPT Mon Aug 10 16:58:35 BST 2020 aarch64GNU/Linux

$ py --version
Python 3.7.3

$ for((i=0;i<5;i++)); do cat InputText.txt | py time_comp.py; done
0.12080025672912598
0.10874629020690918
0.1127462387084961
0.1103978157043457
0.15588116645812988

$ for((i=0;i<5;i++)); do cat InputText.txt | py time_map.py; done
0.11949372291564941
0.11281895637512207
0.11392450332641602
0.2708289623260498
0.276080846786499

平均を計算すると、内包表記は0.1217、mapは0.1786ぐらいでしょうか。ここでは内包表記が優位になりました。

Windowsでやりました。

> cmd /c ver

Microsoft Windows [Version 10.0.18363.1110]
> py --version
Python 3.8.2

> for($i = 0;$i -le 5; $i++){cat .\InputText.txt | py .\time_comp.py}
1.0488629341125488
0.7845804691314697
1.163966178894043
0.7295846939086914
0.7399096488952637
0.8466687202453613

> for($i = 0;$i -le 5; $i++){cat .\InputText.txt | py .\time_map.py}
0.5758388042449951
0.5823671817779541
0.6683478355407715
0.6919825077056885
0.6597652435302734
0.6140100955963135

Windowsおっそ明らかな有意差が出ましたね、結構OSによる差があるみたいです。

結論

 結論としては、『環境や状況に左右されやすく、どっちが良いとは断言できない。』という感じでしょうか。自分はmapの方が明らかに早いからよくつかわれていているのだと思い込んでいましたが、そういうわけでは無いみたいですね。それともまた他のアーキテクチャやOSでは差が出るのか…inputをsys.stdinにしたら変わるのか、そもそもリストアペンドが遅くて差が隠れてしまっているのではないか、メモリの効率はいかがなのかなど他にも検証事項はありそうですが、この辺でいったん終わりにしたいと思います。
 ここまでお読みいただいてありがとうございました。皆さんはどちら派ですか?

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2