やりたいこと
dequeで範囲を指定して値を取得したい。
調べても出てこなかったので、無理そうならlistに変換しようと思いますが、
スマートな方法があればご教授ください。
例
_deque = collections.deque(maxlen=1000) for i in range(1000) _deque.append(i) # 1000個の値がappendされた状態で末尾から100個、500個のように任意の値を取得したい。(取り出しはしなくてよい)
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

回答2件
0
itertools.islice
を使うと良いと思います。-> ドキュメント
投稿2019/02/03 05:05
総合スコア6149
0
ベストアンサー
一般的にこれが最良という方法はありません。
dequeはどういうアルゴリズムで動いているかを中までわかった上でないと速くならないし、実際にどのぐらいのデータをどのように扱うかを前提にしないと使うべきなのか判断できない、かなり低水準なライブラリなのです。
(だからこそスライス実装を提供していないように思えます)
長いdequeから、少数の末尾を取り出すだいたいは速い方法は
python
1def slice_last_n(d, n): 2 t = [d.pop() for _i in range(n)][::-1] 3 d.extend(t) 4 return t
こうでしょう。(もっときれいに書けないか……、という気はします)
ipythonの%timeitでの計測
plain
1In : x = deque(range(1000000), 1000000) 2 3In : %timeit y = slice_last_n(x, 100) 49.9 µs ± 175 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each) 5 6In : %timeit y = list(x)[-100:] 711 ms ± 131 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
でも長いdequeから、長い末尾を取り出すならlistにする方が速いです。
plain
1In : %timeit y = slice_last_n(x, 900000) 2106 ms ± 653 µs per loop (mean ± std. dev. of 7 runs, 10 loops each) 3 4In : %timeit y = list(x)[-900000:] 519.3 ms ± 429 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
質問のような短いdequeから、短い末尾を取り出すなら、だいたいはlistにするのが速く、コードもわかりやすいはずです。
plain
1In : x = deque(range(1000), 1000) 2 3In : %timeit y = slice_last_n(x, 100) 410.3 µs ± 282 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each) 5 6In : %timeit y = list(x)[-100:] 75.93 µs ± 636 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
追記
https://docs.python.org/ja/3/library/collections.html#deque-recipes
To implement deque slicing, use a similar approach applying rotate() to bring a target element to the left side of the deque. Remove old entries with popleft(), add new entries with extend(), and then reverse the rotation. With minor variations on that approach, it is easy to implement Forth style stack manipulations such as dup, drop, swap, over, pick, rot, and roll.
python
1def slice_deque(d, i, n): 2 d.rotate(-i) 3 t = [d.popleft() for _i in range(n)] 4 d.extend(t) 5 d.rotate(i+n) 6 return t
plain
1In : x = deque(range(1000000), 1000000) 2 3In : %timeit y = list(islice(x, 100, 10)) 4808 ns ± 12.6 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each) 5 6In : %timeit slice_deque(x, 100,10) 71.99 µs ± 52.5 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each) 8 9In %timeit y = list(islice(x, 700000, 10)) 102.31 ms ± 44.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) 11 12In : %timeit slice_deque(x, 700000,10) 13257 µs ± 19.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
追記
長いdequeから、長い部分要素を取り出すならisliceの方が有利です。(popを繰り返す操作がネックになりますから)
plain
1In : %timeit y = list(islice(x, 700000, 100000)) 22.21 ms ± 24.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) 3 4In : %timeit slice_deque(x, 700000, 100000) 59.72 ms ± 48.1 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
投稿2019/02/03 00:07
編集2019/02/03 08:29総合スコア11288
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/02/03 07:19
2019/02/03 07:39
2019/02/03 08:27
2019/02/03 08:53
2019/02/03 09:16 編集
2019/02/03 10:38