Python'da bir listeyi ters sırada döndürme


702

Böylece başlayıp len(collection)bitebilirim collection[0].

Ayrıca döngü dizinine erişmek istiyorum.

Yanıtlar:


1184

Yerleşik reversed()işlevi kullanın :

>>> a = ["foo", "bar", "baz"]
>>> for i in reversed(a):
...     print(i)
... 
baz
bar
foo

Orijinal dizine erişmek için enumerate(), listeye iletmeden önce listenizde kullanın reversed():

>>> for i, e in reversed(list(enumerate(a))):
...     print(i, e)
... 
2 baz
1 bar
0 foo

Yana enumerate()döner bir jeneratör ve jeneratörler geri alınamaz, bir dönüştürmek için gereken listilk.


131
Hiçbir kopya oluşturulmaz, öğeler hareket halindeyken anında ters çevrilir! Bu, tüm bu yineleme işlevlerinin (hepsi “ed” ile biten) önemli bir özelliğidir.
Konrad Rudolph

9
@Greg Hewgill Hayır, orijinalin üzerinde bir yineleyici, kopya oluşturulmaz!
André

92
Karışıklığı önlemek için: reversed()listeyi değiştirmez. reversed()listenin bir kopyasını oluşturmaz (aksi takdirde O (N) ek bellek gerektirir). Listeyi değiştirmeniz gerekiyorsa alist.reverse(); listenin bir kopyasına ihtiyacınız varsa ters sipariş kullanın alist[::-1].
jfs

92
bu cevapta list (enumerate (a)) bir kopya oluşturur.
Triptik

43
@ JF, reversed () bir kopya oluşturmaz, ancak list (enumerate ()) bir kopya yapar.
Triptych

173

Yapabilirsin:

for item in my_list[::-1]:
    print item

(Ya da for döngüsünde ne yapmak isterseniz.)

[::-1]Dilim döngü listeyi tersine çevirir (ancak reklamları listesi "kalıcı" değiştirmez).


24
[::-1]sığ bir kopya oluşturur, bu nedenle diziyi "kalıcı" veya "geçici" olarak değiştirmez.
jfs

6
Bu, en azından Python 2.7 (test edilmiş) altında, tersine çevrilmekten biraz daha yavaştır.
kgriffs

14
Bu cevap nasıl çalışır : listenin dilimlenmiş bir kopyasını şu parametrelerle oluşturur: başlangıç ​​noktası : belirtilmemiş (listenin uzunluğu olur, böylece sonunda başlar), bitiş noktası : belirtilmemiş ( 0muhtemelen -1başlangıçta biter dışında sihirli bir sayı olur) ) ve adım : -1(listede, 1her seferinde öğe arasında geriye doğru yinelenir ).
Edward

1
Bunu da test ettim (python 2.7) ve [:: - 1] vsreversed()
RustyShackleford

67

Döngü dizinine ihtiyacınız varsa ve tüm listeyi iki kez dolaşmak veya fazladan bellek kullanmak istemiyorsanız, bir jeneratör yazarım.

def reverse_enum(L):
   for index in reversed(xrange(len(L))):
      yield index, L[index]

L = ['foo', 'bar', 'bas']
for index, item in reverse_enum(L):
   print index, item

3
Enumerate_reversed işlevini çağırırım, ancak bu sadece benim zevkim olabilir. Cevabınızın bu soru için en temiz olduğuna inanıyorum.
tzot

1
reversed(xrange(len(L)))ile aynı endeksleri üretir xrange(len(L)-1, -1, -1).
jfs

2
Anlamak için daha az hareketli parçayı tercih ederim:for index, item in enumerate(reversed(L)): print len(L)-1-index, item
Don Kirkby

2
@Triptych Sadece ters () numaralandırması ters dizinler vermeyeceği gerçeği ile başa çıkmak zorunda kaldı ve kodunuz çok yardımcı oldu. Bu yöntem standart kütüphanede olmalıdır.
oski86

2
reversed (xrange ()), bir xrange nesnesinin __reversed__ yönteminin yanı sıra __len__ ve __getitem__ yöntemlerine sahip olması nedeniyle çalışır ve tersine çevrilmiş bunu algılayıp kullanabilir. Ancak numaralandırılmış bir nesnede __reversed__, __len__ veya __getitem__ yoktur. Ama neden numaralandırılmıyor onları? Bunu bilmiyorum.
FutureNerd

60

Bu şekilde yapılabilir:

aralıktaki i için (len (toplama) -1, -1, -1):
    koleksiyonu yazdır [i]

    python 3 için # print (koleksiyon [i]). +

Yani tahmininiz oldukça yakındı :) Biraz garip ama temelde şöyle diyor: 1'den daha az ile başlayın, len(collection)-1'den hemen önce -1'e kadar olana kadar devam edin.

Fyi, helpişlev Python konsolundan bir şey için dokümanları görüntülemenize izin verdiği için çok kullanışlıdır, örneğin:

help(range)


1
3.0'dan önceki Python sürümleri için, xrange'in büyük len (koleksiyon) aralığı için tercih edilebilir olduğuna inanıyorum.
Brian M. Hunt

Doğru olduğuna inanıyorum :) iirc, range () bir dizi olarak tüm aralığı oluşturur, ancak xrange () sadece gerektiğinde değerleri üreten bir yineleyici döndürür.
Alan Rowarth

11
Bu pek çok kişi için çok garip görünüyor -1. Ben sadece söyleyebilirimreversed(xrange(len(collection)))
musiphil

22

reversedYerleşik fonksiyonu kullanışlıdır:

for item in reversed(sequence):

Dokümantasyon ters yönelik sınırlamaları açıklar.

Bir dizini dizin ile birlikte ters bir şekilde yürümek zorunda olduğu durumlarda (örneğin, sıra uzunluğunu değiştiren yerinde değişiklikler için), bu işlev benim bir kodutil modülü tanımladı:

import itertools
def reversed_enumerate(sequence):
    return itertools.izip(
        reversed(xrange(len(sequence))),
        reversed(sequence),
    )

Bu, dizinin bir kopyasını oluşturmaktan kaçınır. Açıkçası, reversedsınırlamalar hala geçerlidir.


9

Yeni bir liste oluşturmadan, dizine ekleyerek yapabilirsiniz:

>>> foo = ['1a','2b','3c','4d']
>>> for i in range(len(foo)):
...     print foo[-(i+1)]
...
4d
3c
2b
1a
>>>

VEYA

>>> length = len(foo)
>>> for i in range(length):
...     print foo[length-i-1]
...
4d
3c
2b
1a
>>>

9
>>> l = ["a","b","c","d"]
>>> l.reverse()
>>> l
['d', 'c', 'b', 'a']

VEYA

>>> print l[::-1]
['d', 'c', 'b', 'a']

7

Tek katmanlı jeneratör yaklaşımını seviyorum:

((i, sequence[i]) for i in reversed(xrange(len(sequence))))

7

Ayrıca, "aralık" veya "sayma" işlevlerinden birini kullanabilirsiniz. Aşağıdaki gibi:

a = ["foo", "bar", "baz"]
for i in range(len(a)-1, -1, -1):
    print(i, a[i])

3 baz
2 bar
1 foo

Ayrıca itertools "count" kullanabilirsiniz aşağıdaki gibi:

a = ["foo", "bar", "baz"]
from itertools import count, takewhile

def larger_than_0(x):
    return x > 0

for x in takewhile(larger_than_0, count(3, -1)):
    print(x, a[x-1])

3 baz
2 bar
1 foo

İlk bloğunuzdaki kod doğru çıktıyı üretmez; çıktı aslında3 foo\n2 bar\n1 baz
amiller27

İlk örnekte "a [i-1]" kullanmaktan kaçınmak için, "aralık (len (a) -1, -1, -1)" aralığını kullanın. Bu daha basit.
Francisc


4

İthalatı olmayan bir yaklaşım:

for i in range(1,len(arr)+1):
    print(arr[-i])

veya

for i in arr[::-1]:
    print(i)

3
def reverse(spam):
    k = []
    for i in spam:
        k.insert(0,i)
    return "".join(k)

3

ne kadar değerli olursa olsun böyle yapabilirsiniz. Çok basit.

a = [1, 2, 3, 4, 5, 6, 7]
for x in xrange(len(a)):
    x += 1
    print a[-x]

1
Ayrıca print a[-(x+1)], dizinin gövdesinde dizini yeniden atamaktan da kaçınabilirsiniz.
Malcolm

2

reverse(enumerate(collection))Python 3'te başarmanın etkileyici bir yolu :

zip(reversed(range(len(collection))), reversed(collection))

python 2'de:

izip(reversed(xrange(len(collection))), reversed(collection))

Bunun için neden kestirme bir elimiz olmadığından emin değilim, örneğin:

def reversed_enumerate(collection):
    return zip(reversed(range(len(collection))), reversed(collection))

ya da neden sahip değiliz reversed_range()


2

Dizine ihtiyacınız varsa ve listeniz küçükse, en okunaklı yol reversed(list(enumerate(your_list)))kabul edilen yanıtın söylediği gibi yapmaktır . Ama bu liste sizin belleğin büyük bir bölümünü kaplıyor yüzden eğer tarafından döndürülen dizini çıkarmak gerekecek, listenizin bir kopyasını oluşturur enumerate(reversed())dan len()-1.

Sadece bir kez yapmanız gerekiyorsa:

a = ['b', 'd', 'c', 'a']

for index, value in enumerate(reversed(a)):
    index = len(a)-1 - index

    do_something(index, value)

veya bunu birkaç kez yapmanız gerekiyorsa bir jeneratör kullanmalısınız:

def enumerate_reversed(lyst):
    for index, value in enumerate(reversed(lyst)):
        index = len(lyst)-1 - index
        yield index, value

for index, value in enumerate_reversed(a):
    do_something(index, value)

1

ters fonksiyon burada işe yarar:

myArray = [1,2,3,4]
myArray.reverse()
for x in myArray:
    print x

list.reverse () dönüş değeri yok
Georg Schölly

1

Ayrıca bir whiledöngü de kullanabilirsiniz :

i = len(collection)-1
while i>=0:
    value = collection[i]
    index = i
    i-=1

1

Sıradan bir döngü için negatif bir dizin kullanabilirsiniz:

>>> collection = ["ham", "spam", "eggs", "baked beans"]
>>> for i in range(1, len(collection) + 1):
...     print(collection[-i])
... 
baked beans
eggs
spam
ham

Dizine, koleksiyonun ters çevrilmiş bir kopyası üzerinde ileri doğru yineleniyormuş gibi erişmek için şunu kullanın i - 1:

>>> for i in range(1, len(collection) + 1):
...     print(i-1, collection[-i])
... 
0 baked beans
1 eggs
2 spam
3 ham

Orijinal, ters çevrilmemiş dizine erişmek için şunu kullanın len(collection) - i:

>>> for i in range(1, len(collection) + 1):
...     print(len(collection)-i, collection[-i])
... 
3 baked beans
2 eggs
1 spam
0 ham

1

Dizinin negatif olduğunu düşünmüyorsanız şunları yapabilirsiniz:

>>> a = ["foo", "bar", "baz"]
>>> for i in range(len(a)):
...     print(~i, a[~i]))
-1 baz
-2 bar
-3 foo

1

Bence en zarif yol şu jeneratörü dönüştürmek enumerateve reversedkullanmak

(-(ri+1), val) for ri, val in enumerate(reversed(foo))

enumerateyineleyicinin tersini oluşturur

Misal:

foo = [1,2,3]
bar = [3,6,9]
[
    bar[i] - val
    for i, val in ((-(ri+1), val) for ri, val in enumerate(reversed(foo)))
]

Sonuç:

[6, 4, 2]

0

Diğer cevaplar iyidir, ancak Liste anlama stili olarak yapmak istiyorsanız

collection = ['a','b','c']
[item for item in reversed( collection ) ]

1
Bu tersine çevrilmiş (koleksiyon) ile aynı şey değil mi? Liste kavrayışı eklemek gereksiz hesaplama dışında hiçbir şey yapmaz. Bu, a = [1, 2, 3] 'deki öğe için a = [öğesi, a = [1, 2, 3]' e benzer.
EpicDavi

0

Negatif indeksleri kullanmak için: -1 ile başlayın ve her yinelemede -1 ile geriye gidin.

>>> a = ["foo", "bar", "baz"]
>>> for i in range(-1, -1*(len(a)+1), -1):
...     print i, a[i]
... 
-1 baz
-2 bar
-3 foo

0

Basit bir yol:

n = int(input())
arr = list(map(int, input().split()))

for i in reversed(range(0, n)):
    print("%d %d" %(i, arr[i]))

0
input_list = ['foo','bar','baz']
for i in range(-1,-len(input_list)-1,-1)
    print(input_list[i])

Ben bu da bunu yapmak için basit bir yol olduğunu düşünüyorum ... sonuna kadar okuyun ve liste uzunluğuna kadar azalan tutmak, çünkü biz asla "son" endeksi yürütmek dolayısıyla -1 de eklendi


0

Görevin bir listede (yani geriye doğru bakarken ilk) bazı koşulları karşılayan son elemanı bulmak olduğunu varsayarsak, aşağıdaki sayıları alıyorum:

>>> min(timeit.repeat('for i in xrange(len(xs)-1,-1,-1):\n    if 128 == xs[i]: break', setup='xs, n = range(256), 0', repeat=8))
4.6937971115112305
>>> min(timeit.repeat('for i in reversed(xrange(0, len(xs))):\n    if 128 == xs[i]: break', setup='xs, n = range(256), 0', repeat=8))
4.809093952178955
>>> min(timeit.repeat('for i, x in enumerate(reversed(xs), 1):\n    if 128 == x: break', setup='xs, n = range(256), 0', repeat=8))
4.931743860244751
>>> min(timeit.repeat('for i, x in enumerate(xs[::-1]):\n    if 128 == x: break', setup='xs, n = range(256), 0', repeat=8))
5.548468112945557
>>> min(timeit.repeat('for i in xrange(len(xs), 0, -1):\n    if 128 == xs[i - 1]: break', setup='xs, n = range(256), 0', repeat=8))
6.286104917526245
>>> min(timeit.repeat('i = len(xs)\nwhile 0 < i:\n    i -= 1\n    if 128 == xs[i]: break', setup='xs, n = range(256), 0', repeat=8))
8.384078979492188

Yani, en çirkin seçenek xrange(len(xs)-1,-1,-1)en hızlısıdır.


-1

bir jeneratör kullanabilirsiniz:

li = [1,2,3,4,5,6]
len_li = len(li)
gen = (len_li-1-i for i in range(len_li))

en sonunda:

for i in gen:
    print(li[i])

Umarım bu sana yardımcı olur.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.