Umkehren einer Liste mit Slice-Notation

79

im folgenden Beispiel:

foo = ['red', 'white', 'blue', 1, 2, 3]

Dabei foo[0:6:1]werden alle Elemente in foo gedruckt. Das foo[6:0:-1]1. oder 0. Element wird jedoch weggelassen.

>>> foo[6:0:-1]
[3, 2, 1, 'blue', 'white']

Ich verstehe, dass ich foo.reverse () oder foo [:: - 1] verwenden kann, um die Liste in umgekehrter Reihenfolge zu drucken, aber ich versuche zu verstehen, warum foo [6: 0: -1] nicht die gesamte Liste druckt ?

user737079
quelle
3
Beachten Sie auch die foo[7:None:-1]Möglichkeit :)
tzot
1
Ich habe noch nie Python verwendet, bevor ich nur versucht habe, die Slice-Notation zu verstehen. Meine Frage ist, warum foo [6: 0: -1] keinen Indexfehler auslöst. Interessiert sich Python nicht dafür? weil der Index 6 im obigen Beispielarray nicht verfügbar ist.
Mubashar
3
@MubasharAhmad Slicing indiziert nicht und gibt keinen Fehler aus, wenn die Grenzen überschritten werden. Die Indizierung löst jedoch Ausnahmen aus, wenn sie außerhalb der Grenzen liegt.
Huggie

Antworten:

151

Kurznotiz:

[ <first element to include> : <first element to exclude> : <step> ]

Wenn Sie das erste Element beim Umkehren einer Liste einschließen möchten, lassen Sie das mittlere Element wie folgt leer:

foo[::-1]

Hier finden Sie auch einige gute Informationen zu Python-Slices im Allgemeinen:
Erläutern Sie die Slice-Notation von Python

Andrew Clark
quelle
42
Dies: [ <first element to include> : <first element to exclude> : <step> ]ist die klarste Erklärung für die Slice-Syntax, die ich gesehen habe. Wenn man es "erstes auszuschließendes Element" nennt, wird wirklich klar, was los ist.
Schof
Was ist mit negativem Schneiden mit negativen Schritten? Ich verstehe es immer noch nicht.
Huggie
6
Wenn Sie einen negativen Index entweder als <first element to include>oder als Index <first element to exclude>am Ende der Liste verwenden, -1ist dies auch das letzte Element, -2das vorletzte Element usw. So x[-1:-4:-1]würden beispielsweise die letzten drei Elemente xin umgekehrter Reihenfolge abgerufen. Sie können dies also so interpretieren, dass Sie "rückwärts gehen und jedes Element ( -1Schritt) vom letzten Element in der Liste ( -1 <first element to include>) bis zum vierten Element vom Ende ( -4 <first element to include>) nehmen, aber nicht einbeziehen ".
Andrew Clark
1
Beim Umkehren (dh wenn <step>ja -1) hilft es mir zu denken <first element to include, moving from right to left>. So erhalten Sie die nElemente "ganz links" aus einer Liste in umgekehrter Reihenfolge : foo[n-1::-1]. So erhalten Sie die nElemente "ganz rechts" in umgekehrter Reihenfolge : foo[-1:-n-1:-1].
DJVG
1
Wie macht man das erste Element, das "das Element vorher foo[0]" ausschließt?
BallpointBen
9

Wenn Sie Probleme haben, sich an die Slice-Notation zu erinnern, können Sie versuchen, den Hokey Cokey auszuführen :

[ In : Out : Schütteln Sie alles über ]

[Erstes Element in clude: Erstes Element zu verlassen out : Der Schritt zur Verwendung]

YMMV

Kapitän Lepton
quelle
7

... warum druckt foo [6: 0: -1] nicht die gesamte Liste?

Weil der Mittelwert eher der exklusive als der inklusive Stoppwert ist. Die Intervallnotation lautet [Start, Stopp].

Genau so funktioniert der [x] -Bereich:

>>> range(6, 0, -1)
[6, 5, 4, 3, 2, 1]

Dies sind die Indizes, die in Ihre resultierende Liste aufgenommen werden, und sie enthalten keine 0 für das erste Element.

>>> range(6, -1, -1)
[6, 5, 4, 3, 2, 1, 0]

Eine andere Sichtweise ist:

>>> L = ['red', 'white', 'blue', 1, 2, 3]
>>> L[0:6:1]
['red', 'white', 'blue', 1, 2, 3]
>>> len(L)
6
>>> L[5]
3
>>> L[6]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list index out of range

Der Index 6 liegt jenseits (genau eins) der gültigen Indizes für L und schließt ihn daher als ausgeschlossenen Stoppwert aus dem Bereich aus:

>>> range(0, 6, 1)
[0, 1, 2, 3, 4, 5]

Gibt Ihnen weiterhin Indizes für jedes Element in der Liste.

Fred Nurk
quelle
1
rangekann es, aber Slice kann es nicht, weil -1es das letzte Element ist. Also l=[1, 2, 3], l[2:-1:-1] == [].
Simin Jie
6

Diese Antwort mag etwas veraltet sein, aber sie könnte für jemanden hilfreich sein, der an demselben Problem festhält. Sie können eine umgekehrte Liste mit einem beliebigen Ende erhalten - bis zu 0 Index, indem Sie das zweite In-Place-Slice wie folgt anwenden:

>>> L = list(range(10))
>>> L
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> (start_ex, end) = (7, 0)
>>> L[end:start_ex][::-1]
[6, 5, 4, 3, 2, 1, 0]
Emreu
quelle
1
Dies ist eigentlich ziemlich nützlich, da Sie für alle Fälle die gleiche Syntax verwenden können. Sie müssen 0 nicht als Sonderfall behandeln.
Tom Zych
Dies ist sinnvoller als das Standardverhalten von Python / numpy für negatives Schneiden, da normalerweise ein Bild oder ein Tensor, der an einer bestimmten Kante ausgerichtet ist, geschnitten und / oder umgekehrt werden soll, während Python / numpy die letzte Zeile / Spalte der Daten o_O verlieren.
Dwayne Robinson
1

Verwenden

>>>foo[::-1]

Dies zeigt die Umkehrung der Liste vom Endelement bis zum Start an.

Ashmita Dutta
quelle
1

Sie können es zum Laufen bringen, wenn Sie einen negativen Stoppwert verwenden. Versuche dies:

foo[-1:-7:-1]
myQwil
quelle
0

Ergänzen. Schritt um 2 umkehren:

A = [1,2,2,3,3]
n = len(A)
res = [None] * n
mid = n//2 + 1 if n%2 == 1 else n//2

res[0::2] = A[0:mid][::-1]
res[1::2] = A[0:mid][::-1]
print(res)

[2, 3, 2, 3, 1]

Charlie 木匠
quelle
0

Die Antwort von Andrew Clark ein bisschen mehr formalisieren :

Angenommen, die Liste vund das v[n1:n2:n3]Slice. n1ist Anfangsposition, n2ist Endposition und n3ist Schritt

Schreiben wir einen Pseucode auf Python-Weise:

n3 = 1  if (n3 is missing) else n3
if n3==0:
   raise exception # error, undefined step

Erster Teil: n3 positiv

if n3>0:
   slice direction is from left to right, the most common direction         

   n1 is left slice position in `v` 
   if n1 is missing: 
      n1 = 0   # initial position
   if n1>=0:
      n1 is a normal position
   else: 
     (-n1-1) is the position in the list from right to left 

   n2 is right slice position in `v` 
   if n2 is missing: 
      n2 = len(x)  # after final position
   if n2>=0:
      n2 is a normal final position (exclusive)
   else: 
      -n2-1 é the final position in the list from right to left 
       (exclusive)

Zweiter Teil: n3 negativ

else: 
  slice direction is from right to left (inverse direction)

  n1 is right slice position in `v` 
  if n1 is missing: 
     n1 = -1   # final position is last position in the list.
  if n1>=0:
     n1 is a normal position
  else: 
     (-n1-1) is the position in the list from right to left 

  n2 is  left slice position in `v` 
  if n2 is missing: 
     n2 = -len(x)-1   # before 1st character  (exclusive)
  if n2>=0:
     n2 is a normal final position (exclusive)
  else: 
     -n2-1 is the ending position in the list from right to left 
     (exclusive)

Nun das ursprüngliche Problem: Wie kann man eine Liste mit Slice-Notation umkehren?

L = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(L(::-1)) # [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]

Warum?
n1 is missing and n3<0 => n1=0
n2 is missing and n3<0 => n2 = -len(x)-1

Damit L(::-1) == L(-1:-11:-1)

Paulo Buchsbaum
quelle