Edited at

インデックスが i の要素を除いたリストを得るには……?

More than 1 year has passed since last update.

リストitems変更を加えずitems[i]を除いたリストを得るのに最も速い書き方あるいは,そこそこ速くてスマートな書き方が気になります(数学でたまに i 番目を除く,みたいなのが欲しくなるので).

Jupyter の %timeit で計測してみました.


numpyを使わない場合

items = list(range(1000000))

i = 17 #適当


スライスの結合

%timeit items[:i] + items[i+1:]

11.2 ms ± 349 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)


内包表記(enumerate使用)

%timeit [item for k, item in enumerate(items) if k != i]

65.1 ms ± 212 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)


内包表記

%timeit [items[k] for k in range(len(items)) if k != i]

75.5 ms ± 800 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

スライスの結合の方が圧倒的に速いようです.ちなみに3番目の例より,2番目のenumerateを使った方が速いのはちょっと驚きました.


numpyを使う場合

@antimon2 さんの丸パクですが,以下のような方法があります.

import numpy as np

items = np.arange(1000000)
i = 17


np.hstack

%timeit np.hstack([items[:i], items[i+1:]])

584 µs ± 6.32 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)


np.delete

%timeit np.delete(items, i)

585 µs ± 3.73 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)


ブールインデックス

%timeit items[np.arange(items.size) != i]

1.9 ms ± 5.82 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)


内包表記

%timeit np.array([items[k] for k in range(len(items)) if k != i])

182 ms ± 3.85 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

こちらもやはりスライスの結合がとても速いです.可読性を考えるとそんなに速さが変わらない np.delete がベストでしょうか.

もし,他によいものがあればご教示ください.