Pregunta

Estoy aprendiendo Ruby y acaba de conseguir en algunas cosas acerca de las matrices y rangos. Me he encontrado algo sobre rebanadas de que, si bien es lógico, a primera vista, me confunde un poco cuando miro profundamente en ella.

IRB dice que (2..-1).to_a es una matriz vacía, es decir, no hay valores en el rango, ¿verdad?
Pero si uso ese mismo rango de [:a, :b, :c, :d, :e][2..-1], consigo [:c, :d, :e] atrás en lugar de una matriz vacía.

Ahora, soy consciente de que -1 representa el último elemento de la matriz, por lo que tipo de sentido que lo que me recogieron, lo hizo. Pero si la estufa misma estaría vacía, ¿cómo es que la selección de cualquier cosa?

¿Fue útil?

Solución

Esta es una pregunta fascinante. La respuesta es que no es los elementos individuales de la gama que son inspeccionados al rebanar la matriz, pero los elementos first y last. Específicamente:

>> (2..-1).to_a
=> []
>> (2..-1).first
=> 2
>> (2..-1).last
=> -1

Así los ejemplo funciona, ya que rebana la matriz desde el elemento [2] al elemento [-1].

Si desea una forma coherente de pensar en esto, considere que (2..-1).to_a salidas de los números enteros encuentra entre 2 y -1 (de los cuales hay ninguno), pero que los medios [2..-1] del 2 index a la -1 index .

(Fuente:. array.c y range.c en la fuente de Rubí)

Y, la parte de bonificación complicado: para obtener el significado que estabas pensando, podría utilizar

>> [:a, :b, :c, :d, :e].values_at *(2..-1).to_a
=> []

Otros consejos

En la operación de corte no está viendo la gama como Range per se, es solo mirar los valores de los puntos finales, en este caso 2 y -1. Desde -1 tiene un significado especial (es decir, último elemento de la lista) simplemente devuelve todo, desde el elemento en la posición 2 al final de la lista. No pensar en él como un Range aquí, sólo pensar en ella como una manera conveniente de pasar en dos números (que expresan dos puntos finales).

El método Array#[] no utiliza el intervalo como un intervalo (es decir, que no llama include? en él o algo por el estilo); sólo se necesita los dos números fuera de él y comprueba si es exclusiva.

Se puede imaginar a parecer algo como esto (aunque el [] real está implementado en C, no en Rubí , y por supuesto también maneja argumentos distintos rangos):

def [](range)
  start = range.begin
  length = range.end - start
  length -= 1 if range.exclude_end?
  slice(start, length)
end
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top