¿Cómo devolver una parte de una matriz en Ruby?

125

Con una lista en Python, puedo devolver una parte usando el siguiente código:

foo = [1,2,3,4,5,6]
bar = [10,20,30,40,50,60]
half = len(foo) / 2
foobar = foo[:half] + bar[half:]

Como Ruby hace todo en matrices, me pregunto si hay algo similar a eso.

Christian Stade-Schuldt
fuente

Respuestas:

192

Sí, Ruby tiene una sintaxis de corte de matriz muy similar a Python. Aquí está la ridocumentación para el método de índice de matriz:

--------------------------------------------------------------- Array#[]
     array[index]                -> obj      or nil
     array[start, length]        -> an_array or nil
     array[range]                -> an_array or nil
     array.slice(index)          -> obj      or nil
     array.slice(start, length)  -> an_array or nil
     array.slice(range)          -> an_array or nil
------------------------------------------------------------------------
     Element Reference---Returns the element at index, or returns a 
     subarray starting at start and continuing for length elements, or 
     returns a subarray specified by range. Negative indices count 
     backward from the end of the array (-1 is the last element). 
     Returns nil if the index (or starting index) are out of range.

        a = [ "a", "b", "c", "d", "e" ]
        a[2] +  a[0] + a[1]    #=> "cab"
        a[6]                   #=> nil
        a[1, 2]                #=> [ "b", "c" ]
        a[1..3]                #=> [ "b", "c", "d" ]
        a[4..7]                #=> [ "e" ]
        a[6..10]               #=> nil
        a[-3, 3]               #=> [ "c", "d", "e" ]
        # special cases
        a[5]                   #=> nil
        a[6, 1]                #=> nil
        a[5, 1]                #=> []
        a[5..10]               #=> []
Jeremy Ruten
fuente
55
¿Por qué es un [5, 1] ​​diferente de un [6, 1]?
dertoni
25
a[2..-1]para pasar del tercer elemento al último. a[2...-1]para ir desde el tercer elemento hasta el segundo último elemento.
Programador inteligente
1
@Rafeh aplaude, preguntándose cómo funciona esta basura, -1 hizo el truco
Ben Sinclair
La sintaxis de @CleverProgrammer está mucho más cerca de Python que la respuesta aceptada. Amo a Ruby, pero debo decir que la sintaxis de Python es más corta y clara. Como beneficio adicional, es posible especificar el paso:range(10)[:5:-1]
Eric Duminil
27

Si desea dividir / cortar la matriz en un índice i,

arr = arr.drop(i)

> arr = [1,2,3,4,5]
 => [1, 2, 3, 4, 5] 
> arr.drop(2)
 => [3, 4, 5] 
Lenin Raj Rajasekaran
fuente
17

Puede usar slice () para esto:

>> foo = [1,2,3,4,5,6]
=> [1, 2, 3, 4, 5, 6]
>> bar = [10,20,30,40,50,60]
=> [10, 20, 30, 40, 50, 60]
>> half = foo.length / 2
=> 3
>> foobar = foo.slice(0, half) + bar.slice(half, foo.length)
=> [1, 2, 3, 40, 50, 60]

Por cierto, que yo sepa, las "listas" de Python se implementan de manera eficiente en forma dinámica. La inserción al principio está en O (n), la inserción al final se amortiza O (1), el acceso aleatorio es O (1).

Manuel
fuente
¿Te refieres a usar la matriz de barras en la segunda rebanada?
Samuel
FYI: slice!()no modifica la matriz en su lugar, sino que "elimina los elementos dados por un índice (opcionalmente hasta elementos de longitud) o por un rango". por ruby-doc.org/core-2.2.3/Array.html#method-i-slice-21
Joshua Pinter el
7

otra forma es usar el método de rango

foo = [1,2,3,4,5,6]
bar = [10,20,30,40,50,60]
a = foo[0...3]
b = bar[3...6]

print a + b 
=> [1, 2, 3, 40, 50 , 60]
usuario3449311
fuente
3

Ruby 2.6 Rangos sin fin / sin fin

(..1)
# or
(...1)

(1..)
# or
(1...)

[1,2,3,4,5,6][..3]
=> [1, 2, 3, 4]

[1,2,3,4,5,6][...3]
 => [1, 2, 3]

ROLES = %w[superadmin manager admin contact user]
ROLES[ROLES.index('admin')..]
=> ["admin", "contact", "user"]
PGill
fuente
2

Me gustan los rangos para esto:

def first_half(list)
  list[0...(list.length / 2)]
end

def last_half(list)
  list[(list.length / 2)..list.length]
end

Sin embargo, tenga mucho cuidado sobre si el punto final está incluido en su rango. Esto se vuelve crítico en una lista de longitud impar donde necesita elegir dónde va a romper el medio. De lo contrario, terminarás contando dos veces el elemento del medio.

El ejemplo anterior consistentemente pondrá el elemento del medio en la última mitad.

laberinto
fuente
Puede usar (list.length / 2.0).ceilpara poner consistentemente el elemento del medio en la primera mitad si lo necesita.
Sorashi