Todos menos el último elemento de la matriz de Ruby


Digamos que tengo una matriz Ruby

a = [1, 2, 3, 4]

Si quiero todo menos el primer elemento, puedo escribir a.drop(1), lo cual es genial. Sin embargo, si quiero todo menos el último, solo puedo pensar de esta manera

a[0..-2]   # or
a[0...-1]

Pero ninguno de estos parece tan limpio como usar drop. ¿Alguna otra forma incorporada que me esté perdiendo?

 115
Author: Peter, 2009-10-22

14 answers

Quizás...

a = t               # => [1, 2, 3, 4]
a.first a.size - 1  # => [1, 2, 3]

o

a.take 3

o

a.first 3

o

a.pop

Que devolverá el último y dejará el array con todo lo anterior

o hacer que la computadora funcione para su cena:

a.reverse.drop(1).reverse

o

class Array
  def clip n=1
    take size - n
  end
end
a          # => [1, 2, 3, 4]
a.clip     # => [1, 2, 3]
a = a + a  # => [1, 2, 3, 4, 1, 2, 3, 4]
a.clip 2   # => [1, 2, 3, 4, 1, 2]
 110
Author: DigitalRoss,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-22 22:47:42

Por curiosidad, ¿por qué no te gusta a[0...-1]? Desea obtener un segmento de la matriz, por lo que el operador de segmento parece la opción idiomática.

Pero si necesita llamar a esto por todas partes, siempre tiene la opción de agregar un método con un nombre más amigable a la clase Array, como sugirió DigitalRoss. Tal vez así:

class Array
    def drop_last
        self[0...-1]
    end
end
 80
Author: Mirko Froehlich,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-10-24 17:31:52

Otro truco genial

>> *a, b = [1,2,3]
=> [1, 2, 3]
>> a
=> [1, 2]
>> b
=> 3
 49
Author: montrealmike,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-18 14:38:57

Si desea realizar una operación pop() en una matriz (que va a resultar en el último elemento eliminado), pero está interesado en obtener la matriz en lugar de un elemento emergente, puede usar tap(&:pop):

> arr = [1, 2, 3, 4, 5]
> arr.pop
=> 5
> arr
=> [1, 2, 3, 4]
> arr.tap(&:pop)
=> [1, 2, 3]
 31
Author: kogitoja,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-23 12:11:31

¿Qué tal aumentar el método drop en sí, por ejemplo así?

class Array
  def drop(n)
    n < 0 ? self[0...n] : super
  end
end

Entonces puedes usar un tamaño negativo para eliminar elementos del extremo, así:

[1, 2, 3, 4].drop(-1) #=> [1, 2, 3]
[1, 2, 3, 4].drop(-2) #=> [1, 2]
 22
Author: axelarge,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-05-14 18:49:53

Lo hago así:

my_array[0..-2]
 22
Author: pixelearth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-03 15:37:12

a[0...-1] parece la mejor manera. La sintaxis de corte de matriz fue creada exactamente para este propósito...

Alternativamente, si no le importa modificar el array en su lugar, podría llamar a a.pop:

>> a = [1, 2, 3, 4]
>> a.pop
>> a
=> [1, 2, 3]
 18
Author: dbr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-10-24 18:27:25

Este es el camino:

[1,2,3,4,5][0..-1-1]

Pero vamos a explicar cómo funciona esto:

a = [1,2,3,4,5]

El siguiente ejemplo devolverá todos los registros, desde la posición 0 hasta el último

a[0..-1]
=> [1, 2, 3, 4, 5]

El siguiente ejemplo devolverá los registros desde 1 posición hasta el último

a[1..-1]
=> [2, 3, 4, 5]

Y aquí tienes lo que necesitas. El siguiente ejemplo devolverá los registros desde la posición 0 hasta la última-1

a[0..-1-1]
=> [1, 2, 3, 4]
 9
Author: Fran Martinez,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-30 10:18:38

Para deshacerse del último elemento en una línea con el resto regresando

[1, 2, 4, 5, 6].reverse.drop(1).reverse

En serio, sin embargo,

[1,2,3,4][0..-2]
#=> [1,2,3]
 9
Author: boulder_ruby,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-24 02:49:28

¿Ha intentado "tomar"

a.take(3) 
 6
Author: Mike Buckbee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-10-22 01:03:41

Esto hace un nuevo array con todos menos los últimos elementos del original:

ary2 = ary.dup
ary2.pop

Tenga en cuenta que algunos otros han sugerido el uso de #pop. Si está bien modificar la matriz en su lugar, está bien. Si no estás de acuerdo con eso, entonces dup la matriz primero, como en este ejemplo.

 1
Author: alegscogs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-01 19:17:16

A menudo me encuentro queriendo todos menos los últimos n elementos de una matriz. He amañado mi propia función para hacer esto de una manera que encuentro más legible que otras soluciones:

class Array
  def all_but_the_last(n)
    self.first(self.size - n)
  end
end

Ahora puedes hacer lo siguiente:

arr = ["One", "Two", "Three", "Four", "Five"]
# => ["One", "Two", "Three", "Four", "Five"]

arr.all_but_the_last(1)
# => ["One", "Two", "Three", "Four"]

arr.all_but_the_last(3)
# => ["One", "Two"]

arr.all_but_the_last(5)
# => []

arr.all_but_the_last(6)
# ArgumentError: negative array size

He permitido deliberadamente el Argumententerror para que el llamante sea responsable de cómo usan este método. Me encantaría escuchar comentarios / críticas de este enfoque.

 1
Author: Soumya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-20 06:28:09

Respuesta: a.τwτ, pero primero tienes que instalar Pyper...

Pyper intro: ¿Conoces a Lispy car y cdr devolviendo "primero" y "resto" del array? Solo para las necesidades como las tuyas, hice una extensión de este mecanismo Lispy. Se llama pyper, y le permite acceder también a 2nd, rest from 2nd, 3rd, rest from 3d, y también last, todo excepto last, etc. Eso no sería mucho sobre lo que escribir, pero también permite la composición de letras, al igual que caar, cadr, cdadar etc. conocido de Lisp:

# First, gem install pyper
require 'pyper'
include Pyper
a = %w/lorem ipsum dolor sit amet/
# To avoid confusion with other methods, and also because it resembles a rain gutter,
# Greek letter τ is used to delimit Pyper methods:
a.τaτ #=> "lorem"
a.τdτ #=> ["ipsum", "dolor", "sit", "amet"]
a.τbτ #=> "ipsum"
a.τeτ #=> ["dolor", "sit", "amet"]
a.τcτ #=> "dolor" (3rd)
a.τzτ #=> "amet" (last)
a.τyτ #=> "sit" (2nd from the end)
a.τxτ #=> "dolor" (3rd from the end)

Y finalmente, la respuesta a su pregunta:

a.τwτ #=> ["lorem", "ipsum", "dolor", "sit"] (all except last)

Hay más:

a.τuτ #=> ["lorem", "ipsum", "dolor"] (all except last 2)
a.τ1τ #=> ["lorem", "ipsum"] (first 2)
a.τ8τ #=> (last 2)
a.τ7τ #=> (last 3)

Composiciones:

a.τwydτ #=> "olor" (all except 1st letter of the last word of all-except-last array)

También hay más caracteres de comando que solo a..f, u..z y 0..9, más notablemente m, que significa mapa:

a.τwmbτ #=> ["o", "p", "o", "i"] (second letters of all-except-last array)

Pero otros caracteres de comando son demasiado calientes y no son muy fáciles de usar en este momento.

 0
Author: Boris Stitnicky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-22 09:27:21
a = [1,2,3,4]

a[0..(a.length - 2)]
=> [1,2,3]
 -1
Author: George Lucas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-17 17:02:43