Invertir una lista usando notación de sector

80

en el siguiente ejemplo:

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

donde: foo[0:6:1]imprimirá todos los elementos en foo. Sin embargo, foo[6:0:-1]omitirá el primer o el 0º elemento.

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

Entiendo que puedo usar foo.reverse () o foo [:: - 1] para imprimir la lista al revés, pero estoy tratando de entender por qué foo [6: 0: -1] no imprime la lista completa ?

user737079
fuente
3
Tenga en cuenta también la foo[7:None:-1]posibilidad :)
tzot
1
Nunca usé Python antes de tratar de entender la notación de cortes, mi pregunta es por qué foo [6: 0: -1] no arroja un error de índice, ¿no le importa a Python? porque el índice 6 no está disponible en la matriz de ejemplo anterior.
Mubashar
3
@MubasharAhmad Slicing no está indexando y no arroja ningún error al ir más allá de los límites. Sin embargo, la indexación arroja una excepción cuando está fuera de los límites.
huggie

Respuestas:

152

Notación de rebanada en resumen:

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

Si desea incluir el primer elemento al invertir una lista, deje el elemento del medio vacío, así:

foo[::-1]

También puede encontrar buena información sobre las porciones de Python en general aquí: Explica la notación de las porciones de
Python

Andrew Clark
fuente
42
Esta: [ <first element to include> : <first element to exclude> : <step> ]es la explicación más clara de la sintaxis del segmento que he visto. Llamarlo "primer elemento a excluir" realmente hace que sea obvio lo que está sucediendo.
Schof
¿Qué pasa con el corte negativo con pasos negativos? Todavía no lo entiendo.
huggie
6
Cuando usa un índice negativo como <first element to include>o <first element to exclude>está indexando desde la parte posterior de la lista, así -1es el último elemento, -2es el penúltimo elemento, etc. Entonces, por ejemplo, x[-1:-4:-1]obtendría los últimos tres elementos de xen orden inverso. Por lo tanto, puede interpretar esto como "retroceder, tomar cada elemento ( -1paso) desde el último elemento de la lista ( -1 <first element to include>) hasta pero sin incluir el cuarto elemento desde el final ( -4 <first element to include>)".
Andrew Clark
1
Al dar marcha atrás (es decir, si <step>es -1), me ayuda a pensar <first element to include, moving from right to left>. Por lo tanto, para obtener los nelementos "más a la izquierda" de una lista en orden inverso: foo[n-1::-1]. Para obtener los nelementos "más a la derecha" en orden inverso: foo[-1:-n-1:-1].
djvg
1
¿Cómo se hace el primer elemento para excluir "el elemento anterior foo[0]"?
BallpointBen
9

Si tiene problemas para recordar la notación de cortes, puede intentar hacer el Hokey Cokey :

[ Dentro : Fuera : Agítalo todo ]

[Primer elemento a en clude: Primer elemento de dejar a cabo : El paso de uso]

YMMV

Capitán Lepton
fuente
7

... ¿por qué foo [6: 0: -1] no imprime la lista completa?

Porque el valor medio es el valor de parada exclusivo , en lugar de inclusivo. La notación de intervalo es [inicio, parada).

Así es exactamente como funciona el rango [x]:

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

Esos son los índices que se incluyen en su lista resultante y no incluyen 0 para el primer elemento.

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

Otra forma de verlo es:

>>> 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

El índice 6 está más allá (una pasada, precisamente) de los índices válidos para L, por lo que se excluye del rango como valor de parada excluido:

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

Aún le brinda índices para cada elemento de la lista.

Fred Nurk
fuente
1
rangepuede hacerlo pero slice no puede hacerlo, porque -1es el último elemento. Por lo tanto l=[1, 2, 3], l[2:-1:-1] == [].
Simin Jie
6

Esta respuesta puede estar un poco desactualizada, pero podría ser útil para alguien que se haya quedado con el mismo problema. Puede obtener una lista inversa con un final arbitrario, hasta un índice 0, aplicando un segundo segmento en el lugar como este:

>>> 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
fuente
1
En realidad, esto es bastante útil, porque puede usar la misma sintaxis para todos los casos. No tiene que tratar 0 como un caso especial.
Tom Zych
Esto tiene más sentido que el comportamiento predeterminado de Python / numpy para el corte negativo, porque normalmente uno quiere cortar y / o invertir una imagen o tensor alineado con un borde dado, mientras que Python / numpy pierde esa última fila / columna de los datos o_O.
Dwayne Robinson
1

Utilizar

>>>foo[::-1]

Esto muestra el reverso de la lista desde el elemento final hasta el inicio,

Ashmita Dutta
fuente
1

Puede hacer que funcione si usa un valor de parada negativo. Prueba esto:

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

Complemento. para retroceder paso a 2:

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 木匠
fuente
0

formalizando un poco más la respuesta de andrew-clark :

Suponga la lista vy el v[n1:n2:n3]corte. n1es la posición inicial, n2es la posición final y n3es el paso

Escribamos un pseucódigo en forma de Python:

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

Primera parte: n3 positivo

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)

Segunda parte: n3 negativo

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)

Ahora el problema original: ¿Cómo revertir una lista con notación de sector?

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

¿Por qué?
n1 is missing and n3<0 => n1=0
n2 is missing and n3<0 => n2 = -len(x)-1

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

Paulo Buchsbaum
fuente