7

これは非常に単純な質問ですが、満足のいく答えを見つけることができていないようです。

Pythonで、リストの最後の項目をリストの残りの部分を「プッシュ」する最初の項目にするための最良の方法は何ですか。

すること:

>>> a=[1,2,3,4]
>>> a[?????]
[4, 1, 2, 3]

私はいつでもlen、リスト連結で遊ぶことができることを知っています...

>>> a=[1,2,3,4]
>>> [a[len(a)-1]] + a[0:len(a)-1]
[4, 1, 2, 3]

しかし、それは正しく見えません...「Pythonic

前もって感謝します。

4

4 に答える 4

13

スライスはそれよりも少し賢いです。のインデックスを使用して、最後から数えることができます。

a[-1:] + a[:-1]

デモ:

>>> a=[1,2,3,4]
>>> a[-1:] + a[:-1]
[4, 1, 2, 3]

これは、任意の数の要素を前面に移動する場合に機能します。

>>> a[-2:] + a[:-2]
[3, 4, 1, 2]

このようにスライスを使用すると、速度は.insert()+ .pop()(短いリスト)を使用する場合と同等になります。

>>> timeit.timeit('a[-1:] + a[:-1]', 'a=[1,2,3,4]')
0.59950494766235352
>>> timeit.timeit('a.insert(0,a.pop(-1))', 'a=[1,2,3,4]')
0.52790379524230957

ただし、複数の要素をシフトする必要がある場合は、勝ちます。

>>> timeit.timeit('a[-2:] + a[:-2]', 'a=[1,2,3,4]')
0.58687901496887207
>>> timeit.timeit('a.insert(0,a.pop(-1));a.insert(0,a.pop(-1))', 'a=[1,2,3,4]')
1.0615170001983643
于 2012-10-11T17:23:44.687 に答える
8
In [103]: a=[1,2,3,4]

In [104]: a.insert(0,a.pop(-1)) # pop(-1) removes the last element 
                                # and use insert() to insert the popped
                                #  element at 0th endex

In [105]: a
Out[105]: [4, 1, 2, 3]
于 2012-10-11T17:24:11.577 に答える
8

これらの多くを実行している場合は、要求していることを実行するために(メモリに関して)最適化されている dequeを確認することをお勧めします。

from collections import deque

>>> a = deque([1,2,3,4])
>>> a.rotate(1)
... deque([4, 1, 2, 3])

timeit比較しているので...

>>> setup = """from collections import deque
               a = deque([1,2,3,4])"""
>>> print timeit.timeit('a.rotate(1)', setup=setup)
... 0.219103839131
于 2012-10-11T17:36:24.027 に答える
0

@kreativiteaへのコメントで述べたように、任意にアクセスされるリストをダンプする必要がある場合は、並べ替えも必要ない場合があります。代わりに、任意のアクセスジェネレータを設計できます。

size = 10
l = range(size)


# use a generator expression to yield slices of the list according 
# to your own order.
# note that no error checking is enforced, and that overlapping 
# and invalid accessRanges will work, so depending on the usage
# you have for this function, you might want to add some 
# sanity checks, like ensuring no overlap between accessRanges
# and that each item is accessed only once.
def ArbitraryListAccessor(listObj, accessRanges):
    for ar in accessRanges:
        for item in listObj[ar[0]:ar[1]]:
            yield item

# to dump the access-ordered list generator as a real list, you need to
# iterate over it, for example, with a list comprehension:
[i for i in ArbitraryListAccessor(l, ((-1,None), (0,-1)))]
# [9, 0, 1, 2, 3, 4, 5, 6, 7, 8]

dequeよりは低速ですが、新しいリストを作成するよりは高速です。複数の反復の場合、両端キューの約2倍の速度ですが、1回の実行(たとえば、リストを任意の順序で1回読み取る)の場合、同等です(たとえば、マイクロ秒の順序)。

ここでの利点は、使用するランダムアクセス範囲を定義できることです。関数内の範囲をオブジェクトに置き換えて、Slice通常のリストスライスとして実装することもできます(ただし、スライスタプルまたはスライスオブジェクトを提供する必要があります)。

于 2012-10-11T19:15:30.370 に答える