46738


Python のリスト `a` の末尾 n 個の要素を取り出したいです。ただし、n は任意の整数になりえ、n ≦ 0 のときは `[]`、n >
len(a) のときは `a` を返すようにしたいです。

たとえば `a = [1, 2, 3, 4, 5, 6]`, `n = 2` だと、末尾 2 つの `[5, 6]` が返ってくるようにしたいです。

## 試したこと1

[code]

    >>> a[-2:]
    [5, 6]
    
[/code]

スライスを作る方法 `a[m:]` で `m < 0` にすると末尾がとれます。ただしこれだと -len(a) < n ≦ 0
のときに動かしたいようには動きません。特に n = 0 のとき、末尾 0 個ではなく `a` 全体が返ってきてしまいます。

[code]

    >>> # n > len(a) のときはきちんと a が返ってくる
    ... a[-10:]
    [1, 2, 3, 4, 5, 6]
    >>> a[-15:]
    [1, 2, 3, 4, 5, 6]
    >>> # -len(a) < n <= 0 のとき、[] が返ってこない
    ... a[0:]
    [1, 2, 3, 4, 5, 6]
    >>> a[2:]
    [3, 4, 5, 6]
    >>> # n ≦ -len(a) のときは、きちんと [] が返ってくる
    ... a[10:]
    []
    
[/code]

## 試したこと2

[code]

    >>> a[len(a)-2:]
    [5, 6]
    
[/code]

明示的に何個目以降が必要なのかを計算してスライスを作ると末尾がとれます。ただしこれだと len(a) < n < 2*len(a)
のときに動かしたいようには動きません。

[code]

    >>> # len(a) < n < 2*len(a) のとき、a が返ってこない
    ... a[len(a)-10:]
    [3, 4, 5, 6]
    >>> # n >= 2*len(a) のとき、きちんと a が返ってくる
    ... a[len(a)-15:]
    [1, 2, 3, 4, 5, 6]
    >>> # n <= 0 のとき、きちんと [] が返ってくる
    ... a[len(a)-0:]
    []
    >>> a[len(a)+2:]
    []
    >>> a[len(a)+10:]
    []
    
[/code]

## 質問

上 2 つの方法はどちらも 0 < n ≦ len(a) のとき思ったように動作しますが、それ以外のときに思ったようには動いてくれません。

適当な関数を作って if 文で n
を場合分けすれば[上手く動かせます](https://wandbox.org/permlink/qSerWthTWtaYb56M)が、それだと毎回自分で定義しないといけません。もちろんそれを自前のライブラリ化して
`import` しても良いのですが、それよりラクな方法があるなら知りたいです。

  * 組み込みの関数を使って **簡単に** 末尾を取れないのでしょうか？ たとえば `a.last(n)` のように末尾を取れないでしょうか。
  * あるいは、適当な有名ライブラリに末尾を取るための関数があったりしないでしょうか？

環境: Python 3.6.5


CC BY-SA 4.0
2018-07-19T02:21:28.253
46711
2018-07-20T22:23:27.287
2018-07-20T22:23:27.287
19110
19110
question
python
リストの末尾 n 個を取り出したい


`collections.deque` を使う方法もあるかと思います。

[code]

    >>> import collections
    >>> a = [1, 2, 3, 4, 5, 6]
    >>> list(collections.deque(a, 2))
    [5, 6]
    >>> list(collections.deque(a, 0))
    []
    >>> list(collections.deque(a, 8))
    [1, 2, 3, 4, 5, 6]
    
[/code]


CC BY-SA 4.0
2018-07-19T03:14:51.957
46714
2018-07-19T03:14:51.957
46711
answer


[metropolis
さんの回答](https://ja.stackoverflow.com/a/46714/19110)を受けて考えている中で、三項演算子を使って書くとシンプルなことに気づきました。

[code]

    # n が定義されているとして...
    a[-n:] if n > 0 else []
    
[/code]

末尾を取る操作がプログラム中に何回もあったり、メソッドチェーンで繋ぎたかったりするときには若干不便ですが、今回の自分の用途にはこれで充分そうです。

(自己回答できてしまいましたが、こんなことしなくてももっとシンプルに書けるよ、という方法があればご教示頂きたいです。)


CC BY-SA 4.0
2018-07-19T03:27:19.110
46715
2018-07-19T03:42:09.093
2018-07-19T03:42:09.093
19110
19110
46711
answer


どうもイディオムは無さそうですね。  
だとすると、やはり適切な名前で関数を定義するのがPython的かと思いますが、短く書く例も出しておきます。

[code]

    # 意図が通じる限界か
    a[max(0, len(a)-n):]
    
    # False.__index__() == 0 を利用したもの
    a[-n: n>0 and None]
    
[/code]


CC BY-SA 4.0
2018-07-19T16:17:40.017
46738
2018-07-19T16:17:40.017
3054
46711
answer


「後ろから何個」という指定と slice との相性が悪いので, リストをいったん逆順にする方針で考えてみました.

[code]

    # a: リスト, n: 長さ
    list(reversed(list(reversed(a))[:max(0, n)]))
    
    # ↑だと文字数が多いので短縮
    a[::-1][:max(0, n)][::-1]
    
[/code]

ただし, 意図が分かりづらいですし, 複雑な処理ではないのに式が長くなってしまっています.


CC BY-SA 4.0
2018-07-20T01:17:49.057
46750
2018-07-20T01:17:49.057
2281
46711
answer