LoginSignup
0
0

More than 3 years have passed since last update.

python ループ処理速度(append vs reduce)

Posted at

結論

割と大きめのデータ処理をしている時、もっと処理速度を早くしようと思って色々いじっていたら、reduceよりappendの方が断然早かった話

はじめに

実行時間計測に使用するデータはこれで生成

import random
data_list = [random.randint(-2, 2) for _ in range(100000)]

作ったデータをどのように処理したいかというと、
配列のある要素x_nとその要素のひとつ前x_(n-1)を加算した新しい配列を生成したい↓

[1, 2, -1, -2] => [1, 3, 2, 0]

ループ処理

appendメソッドを使う

def append_loop(data):
    out_put = [data[0]]
    for i in data[1:]:
        out_put.append(out_put[-1] + i)
    return out_put

# 実行時間: 0.019423961639404297

appendは破壊的メソッドとよばれ、思わぬバグを発生させることが多く。また空の配列を用意しなくてはいけないため、コード量がその分多くなったりするので割と避けていたが速度は非常に早かった。

reduce

def reduce_append(li, elem):
    return [elem] if not li else li + [li[-1] + elem]

# 実行時間: 11.915228843688965
reduce(reduce_append, data_list, [])

reduceを使う場合は非常にコード簡潔になるが、速度に関しては大きな差が開いている。およそ600倍の時間がかかっている。
これにはif文があるから実行時間が遅くなった可能性があるので、少々可読性は落ちるが、そのパターンも作成

def reduce_append(li, elem):
    return li + [li[-1] + elem]

# 実行時間: 10.55799412727356
reduce(reduce_append, data_list[1:], [data_list[0]])

実行時間は1秒くらいしかかわらなかった。

おまけ

内包表記

[sum(data_list[:i + 1]) for i in range(len(data))]

# 実行時間: 86.43631505966187

一行でかけるが、遅すぎて使い物にならない。sum関数自体にループがあるからしゃーない

再帰関数

@tail_recursion
def recursive_function(result_array, origin_array, index):
    if len(result_array) > 0:
        result_array.append(result_array[-1] + origin_array[index])
    else:
        result_array.append(origin_array[0])
    if len(origin_array) > index + 1:
        return recursive_function(result_array, origin_array, index + 1)

# 実行時間: 0.08165287971496582
recursive_function(result, data_list, 0)

わかりにくいがそこそこはやい。テクニークの練習にはなる。

おわり

append使うのはダサいとか、カッコ悪いとか、初心者とかおもっていたけどちょっと見直しました。まぁ私、初心者なんですが笑
なにか他に良い方法があったら教えてくださいヽ( ◔ ౪ ◔ )ノイッパツデコンパイルトオッタァァァァwwwwww

0
0
3

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
0