Ruby Language
Array
Ricerca…
Sintassi
- a = [] # usando array letterale
- a = Array.new # equivalente all'utilizzo letterale
- a = Array.new (5) # crea una matrice con 5 elementi con valore di zero.
- a = Array.new (5, 0) # crea una matrice con 5 elementi con valore predefinito di 0.
#carta geografica
#map
, fornita da Enumerable, crea una matrice richiamando un blocco su ciascun elemento e raccogliendo i risultati:
[1, 2, 3].map { |i| i * 3 }
# => [3, 6, 9]
['1', '2', '3', '4', '5'].map { |i| i.to_i }
# => [1, 2, 3, 4, 5]
La matrice originale non è stata modificata; viene restituito un nuovo array contenente i valori trasformati nello stesso ordine dei valori di origine. map!
può essere usato se si desidera modificare l'array originale.
Nel metodo map
puoi chiamare il metodo o usare proc a tutti gli elementi dell'array.
# call to_i method on all elements
%w(1 2 3 4 5 6 7 8 9 10).map(&:to_i)
# => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# using proc (lambda) on all elements
%w(1 2 3 4 5 6 7 8 9 10).map(&->(i){ i.to_i * 2})
# => [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
map
è sinonimo di collect
.
Creazione di una matrice con il costruttore letterale []
Gli array possono essere creati racchiudendo un elenco di elementi tra parentesi quadre ( [
e ]
). Gli elementi dell'array in questa notazione sono separati da virgole:
array = [1, 2, 3, 4]
Le matrici possono contenere qualsiasi tipo di oggetti in qualsiasi combinazione senza restrizioni sul tipo:
array = [1, 'b', nil, [3, 4]]
Crea una serie di stringhe
Gli array di stringhe possono essere creati usando la sintassi della stringa percentuale di ruby:
array = %w(one two three four)
Questo è funzionalmente equivalente alla definizione della matrice come:
array = ['one', 'two', 'three', 'four']
Invece di %w()
puoi utilizzare altre coppie di delimitatori corrispondenti: %w{...}
, %w[...]
o %w<...>
.
È anche possibile utilizzare delimitatori arbitrari non alfanumerici, ad esempio: %w!...!
, %w#...#
o %w@...@
.
%W
può essere utilizzato al posto di %w
per incorporare l'interpolazione delle stringhe. Considera quanto segue:
var = 'hello'
%w(#{var}) # => ["\#{var}"]
%W(#{var}) # => ["hello"]
Più parole possono essere interpretate evadendo lo spazio con un \.
%w(Colorado California New\ York) # => ["Colorado", "California", "New York"]
Crea una matrice di simboli
array = %i(one two three four)
Crea l'array [:one, :two, :three, :four]
.
Invece di %i(...)
, puoi usare %i{...}
o %i[...]
o %i!...!
Inoltre, se si desidera utilizzare l'interpolazione, è possibile farlo con %I
a = 'hello'
b = 'goodbye'
array_one = %I(#{a} #{b} world)
array_two = %i(#{a} #{b} world)
Crea gli array: array_one = [:hello, :goodbye, :world]
array_two = [:"\#{a}", :"\#{b}", :world]
array_one = [:hello, :goodbye, :world]
e array_two = [:"\#{a}", :"\#{b}", :world]
Crea array con Array :: new
Una matrice vuota ( []
) può essere creata con il metodo di classe di Array::new
, Array::new
:
Array.new
Per impostare la lunghezza dell'array, passare un argomento numerico:
Array.new 3 #=> [nil, nil, nil]
Esistono due modi per popolare una matrice con valori predefiniti:
- Passa un valore immutabile come secondo argomento.
- Passa un blocco che ottiene l'indice corrente e genera valori mutabili.
Array.new 3, :x #=> [:x, :x, :x]
Array.new(3) { |i| i.to_s } #=> ["0", "1", "2"]
a = Array.new 3, "X" # Not recommended.
a[1].replace "C" # a => ["C", "C", "C"]
b = Array.new(3) { "X" } # The recommended way.
b[1].replace "C" # b => ["X", "C", "X"]
Manipolazione di elementi di matrice
Aggiunta di elementi:
[1, 2, 3] << 4
# => [1, 2, 3, 4]
[1, 2, 3].push(4)
# => [1, 2, 3, 4]
[1, 2, 3].unshift(4)
# => [4, 1, 2, 3]
[1, 2, 3] << [4, 5]
# => [1, 2, 3, [4, 5]]
Rimozione di elementi:
array = [1, 2, 3, 4]
array.pop
# => 4
array
# => [1, 2, 3]
array = [1, 2, 3, 4]
array.shift
# => 1
array
# => [2, 3, 4]
array = [1, 2, 3, 4]
array.delete(1)
# => 1
array
# => [2, 3, 4]
array = [1,2,3,4,5,6]
array.delete_at(2) // delete from index 2
# => 3
array
# => [1,2,4,5,6]
array = [1, 2, 2, 2, 3]
array - [2]
# => [1, 3] # removed all the 2s
array - [2, 3, 4]
# => [1] # the 4 did nothing
Combinare gli array:
[1, 2, 3] + [4, 5, 6]
# => [1, 2, 3, 4, 5, 6]
[1, 2, 3].concat([4, 5, 6])
# => [1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6] - [2, 3]
# => [1, 4, 5, 6]
[1, 2, 3] | [2, 3, 4]
# => [1, 2, 3, 4]
[1, 2, 3] & [3, 4]
# => [3]
Puoi anche moltiplicare gli array, ad es
[1, 2, 3] * 2
# => [1, 2, 3, 1, 2, 3]
Array unione, intersezione e differenza
x = [5, 5, 1, 3]
y = [5, 2, 4, 3]
Union ( |
) contiene elementi di entrambi gli array, con i duplicati rimossi:
x | y
=> [5, 1, 3, 2, 4]
Intersezione ( &
) contiene elementi presenti sia nel primo che nel secondo array:
x & y
=> [5, 3]
Difference ( -
) contiene elementi presenti nel primo array e non presenti nel secondo array:
x - y
=> [1]
Array di filtraggio
Spesso vogliamo operare solo su elementi di un array che soddisfano una condizione specifica:
Selezionare
Restituisce elementi che corrispondono a una condizione specifica
array = [1, 2, 3, 4, 5, 6]
array.select { |number| number > 3 } # => [4, 5, 6]
Rifiutare
Restituisce elementi che non corrispondono a una condizione specifica
array = [1, 2, 3, 4, 5, 6]
array.reject { |number| number > 3 } # => [1, 2, 3]
Sia #select
e #reject
restituiscono un array, quindi possono essere concatenati:
array = [1, 2, 3, 4, 5, 6]
array.select { |number| number > 3 }.reject { |number| number < 5 }
# => [5, 6]
Iniettare, ridurre
Inietta e riduci sono nomi diversi per la stessa cosa. In altre lingue queste funzioni sono spesso chiamate pieghe (come foldl o foldr). Questi metodi sono disponibili su ogni oggetto Enumerable.
Inject prende una funzione a due argomenti e la applica a tutte le coppie di elementi nella matrice.
Per l'array [1, 2, 3]
possiamo aggiungere tutti questi insieme al valore iniziale di zero specificando un valore iniziale e un blocco in questo modo:
[1,2,3].reduce(0) {|a,b| a + b} # => 6
Qui passiamo alla funzione un valore iniziale e un blocco che dice di aggiungere tutti i valori insieme. Il blocco viene prima eseguito con 0
come a
1
come b
, quindi prende il risultato di ciò come il successivo a
, quindi aggiungiamo 1
al secondo valore 2
. Quindi prendiamo il risultato di questo ( 3
) e lo aggiungiamo all'elemento finale nella lista (anche 3
) dandoci il nostro risultato ( 6
).
Se si omette il primo argomento, verrà impostato a
ad essere il primo elemento della lista, quindi l'esempio di cui sopra è la stessa:
[1,2,3].reduce {|a,b| a + b} # => 6
Inoltre, invece di passare un blocco con una funzione, possiamo passare una funzione con nome come simbolo, con un valore iniziale o senza. Con questo, l'esempio precedente potrebbe essere scritto come:
[1,2,3].reduce(0, :+) # => 6
o omettendo il valore iniziale:
[1,2,3].reduce(:+) # => 6
Accesso agli elementi
Puoi accedere agli elementi di un array in base ai loro indici. La numerazione dell'indice di matrice inizia da 0
.
%w(a b c)[0] # => 'a'
%w(a b c)[1] # => 'b'
È possibile ritagliare un array usando l'intervallo
%w(a b c d)[1..2] # => ['b', 'c'] (indices from 1 to 2, including the 2)
%w(a b c d)[1...2] # => ['b'] (indices from 1 to 2, excluding the 2)
Questo restituisce un nuovo array, ma non influenza l'originale. Ruby supporta anche l'uso di indici negativi.
%w(a b c)[-1] # => 'c'
%w(a b c)[-2] # => 'b'
Puoi anche combinare gli indici negativi e quelli positivi
%w(a b c d e)[1...-1] # => ['b', 'c', 'd']
Altri metodi utili
Utilizzare first
per accedere al primo elemento di un array:
[1, 2, 3, 4].first # => 1
O first(n)
per accedere ai primi n
elementi restituiti in un array:
[1, 2, 3, 4].first(2) # => [1, 2]
Allo stesso modo per last
e last(n)
:
[1, 2, 3, 4].last # => 4
[1, 2, 3, 4].last(2) # => [3, 4]
Usa sample
per accedere a un elemento casuale in una matrice:
[1, 2, 3, 4].sample # => 3
[1, 2, 3, 4].sample # => 1
O sample(n)
:
[1, 2, 3, 4].sample(2) # => [2, 1]
[1, 2, 3, 4].sample(2) # => [3, 4]
Array bidimensionale
Usando il Array::new
costruttore Array::new
, puoi inizializzare un array con una determinata dimensione e un nuovo array in ciascuno dei suoi slot. Gli array interni possono anche avere una dimensione e un valore iniziale.
Ad esempio, per creare una matrice 3x4 di zeri:
array = Array.new(3) { Array.new(4) { 0 } }
L'array generato sopra appare come questo se stampato con p
:
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
Puoi leggere o scrivere su elementi come questo:
x = array[0][1]
array[2][3] = 2
Array e l'operatore splat (*)
L'operatore *
può essere utilizzato per decomprimere variabili e array in modo che possano essere passati come singoli argomenti a un metodo.
Questo può essere usato per racchiudere un singolo oggetto in una matrice, se non lo è già:
def wrap_in_array(value)
[*value]
end
wrap_in_array(1)
#> [1]
wrap_in_array([1, 2, 3])
#> [1, 2, 3]
wrap_in_array(nil)
#> []
Nell'esempio precedente, il metodo wrap_in_array
accetta un argomento, value
.
Se value
è una Array
, i suoi elementi vengono decompressi e viene creato un nuovo array contenente tali elementi.
Se value
è un singolo oggetto, viene creato un nuovo array contenente quel singolo oggetto.
Se il value
è nil
, viene restituito un array vuoto.
L'operatore splat è particolarmente utile se usato come argomento nei metodi in alcuni casi. Ad esempio, consente di gestire nil
, valori singoli e matrici in modo coerente:
def list(*values)
values.each do |value|
# do something with value
puts value
end
end
list(100)
#> 100
list([100, 200])
#> 100
#> 200
list(nil)
# nothing is outputted
Decomposizione
Qualsiasi array può essere rapidamente decomposto assegnando i suoi elementi a più variabili. Un semplice esempio:
arr = [1, 2, 3]
# ---
a = arr[0]
b = arr[1]
c = arr[2]
# --- or, the same
a, b, c = arr
Precedendo una variabile con l'operatore splat ( *
) si mette una matrice di tutti gli elementi che non sono stati catturati da altre variabili. Se non ne rimane, viene assegnato un array vuoto. È possibile utilizzare solo uno splat in un singolo compito:
a, *b = arr # a = 1; b = [2, 3]
a, *b, c = arr # a = 1; b = [2]; c = 3
a, b, c, *d = arr # a = 1; b = 2; c = 3; d = []
a, *b, *c = arr # SyntaxError: unexpected *
La decomposizione è sicura e non genera mai errori. nil
sono assegnati dove non ci sono abbastanza elementi, corrispondenti al comportamento dell'operatore []
quando si accede a un indice fuori limite:
arr[9000] # => nil
a, b, c, d = arr # a = 1; b = 2; c = 3; d = nil
La to_ary
tenta di chiamare implicitamente sull'attuale oggetto assegnato. Implementando questo metodo nel tuo tipo hai la possibilità di scomporlo:
class Foo
def to_ary
[1, 2]
end
end
a, b = Foo.new # a = 1; b = 2
Se l'oggetto che si sta respond_to?
non respond_to?
to_ary
, viene considerato come un array a elemento singolo:
1.respond_to?(:to_ary) # => false
a, b = 1 # a = 1; b = nil
La decomposizione può anche essere annidata usando un'espressione di decomposizione cancellata ()
al posto di quello che altrimenti sarebbe un singolo elemento:
arr = [1, [2, 3, 4], 5, 6]
a, (b, *c), *d = arr # a = 1; b = 2; c = [3, 4]; d = [5, 6]
# ^^^^^
Questo è effettivamente l'opposto di Splat .
In realtà, qualsiasi espressione di decomposizione può essere delimitata da ()
. Ma per il primo livello la scomposizione è facoltativa.
a, b = [1, 2]
(a, b) = [1, 2] # the same thing
Edge case: un singolo identificatore non può essere utilizzato come modello destrutturante, sia esso esterno o nidificato:
(a) = [1] # SyntaxError
a, (b) = [1, [2]] # SyntaxError
Quando si assegna un array letterale a un'espressione destrutturante, esterno []
può essere omesso:
a, b = [1, 2]
a, b = 1, 2 # exactly the same
Questo è noto come assegnazione parallela , ma utilizza la stessa decomposizione sotto il cofano. Ciò è particolarmente utile per lo scambio di valori di variabili senza l'utilizzo di variabili temporanee aggiuntive:
t = a; a = b; b = t # an obvious way
a, b = b, a # an idiomatic way
(a, b) = [b, a] # ...and how it works
I valori vengono acquisiti quando si costruisce il lato destro del compito, quindi l'utilizzo delle stesse variabili di origine e destinazione è relativamente sicuro.
Trasforma la matrice multidimensionale in una matrice unidimensionale (appiattita)
[1, 2, [[3, 4], [5]], 6].flatten # => [1, 2, 3, 4, 5, 6]
Se si dispone di un array multidimensionale e occorre renderlo un array semplice (ad esempio unidimensionale), è possibile utilizzare il metodo #flatten
.
Ottieni elementi di array unici
Nel caso in cui sia necessario leggere gli elementi di un array evitando le ripetizioni, si utilizza il metodo #uniq
:
a = [1, 1, 2, 3, 4, 4, 5]
a.uniq
#=> [1, 2, 3, 4, 5]
Invece, se vuoi rimuovere tutti gli elementi duplicati da una matrice, puoi usare #uniq!
metodo:
a = [1, 1, 2, 3, 4, 4, 5]
a.uniq!
#=> [1, 2, 3, 4, 5]
Mentre l'output è lo stesso, #uniq!
memorizza anche il nuovo array:
a = [1, 1, 2, 3, 4, 4, 5]
a.uniq
#=> [1, 2, 3, 4, 5]
a
#=> [1, 1, 2, 3, 4, 4, 5]
a = [1, 1, 2, 3, 4, 4, 5]
a.uniq!
#=> [1, 2, 3, 4, 5]
a
#=> [1, 2, 3, 4, 5]
Ottieni tutte le combinazioni / permutazioni di un array
Il metodo di permutation
, quando chiamato con un blocco produce una matrice bidimensionale che consiste in tutte le sequenze ordinate di una raccolta di numeri.
Se questo metodo viene chiamato senza un blocco, restituirà un enumerator
. Per convertire in un array, chiama il metodo to_a
.
Esempio | Risultato |
---|---|
[1,2,3].permutation | #<Enumerator: [1,2,3]:permutation |
[1,2,3].permutation.to_a | [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]] |
[1,2,3].permutation(2).to_a | [[1,2],[1,3],[2,1],[2,3],[3,1],[3,2]] |
[1,2,3].permutation(4).to_a | [] -> Nessuna permutazione di lunghezza 4 |
Il metodo di combination
, d'altro canto, quando viene chiamato con un blocco produce una matrice bidimensionale costituita da tutte le sequenze di una raccolta di numeri. Diversamente dalla permutazione, l'ordine è disatteso in combinazioni. Ad esempio, [1,2,3]
è uguale a [3,2,1]
Esempio | Risultato |
---|---|
[1,2,3].combination(1) | #<Enumerator: [1,2,3]:combination |
[1,2,3].combination(1).to_a | [[1],[2],[3]] |
[1,2,3].combination(3).to_a | [[1,2,3]] |
[1,2,3].combination(4).to_a | [] -> Nessuna combinazione di lunghezza 4 |
Chiamare il metodo di combinazione da solo risulterà in un enumeratore. Per ottenere un array, chiama il metodo to_a
.
I metodi repeated_combination
e repeated_permutation
sono simili, tranne che lo stesso elemento può essere ripetuto più volte.
Ad esempio le sequenze [1,1]
, [1,3,3,1]
, [3,3,3]
non sarebbero valide in combinazioni e permutazioni regolari.
Esempio | # Combo |
---|---|
[1,2,3].combination(3).to_a.length | 1 |
[1,2,3].repeated_combination(3).to_a.length | 6 |
[1,2,3,4,5].combination(5).to_a.length | 1 |
[1,2,3].repeated_combination(5).to_a.length | 126 |
Crea una matrice di numeri o lettere consecutive
Questo può essere facilmente ottenuto chiamando Enumerable#to_a
su un oggetto Range
:
(1..10).to_a #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
(a..b)
significa che includerà tutti i numeri tra aeb. Per escludere l'ultimo numero, utilizzare a...b
a_range = 1...5
a_range.to_a #=> [1, 2, 3, 4]
o
('a'..'f').to_a #=> ["a", "b", "c", "d", "e", "f"]
('a'...'f').to_a #=> ["a", "b", "c", "d", "e"]
Una comoda scorciatoia per creare un array è [*a..b]
[*1..10] #=> [1,2,3,4,5,6,7,8,9,10]
[*'a'..'f'] #=> ["a", "b", "c", "d", "e", "f"]
Rimuovi tutti gli elementi nil da un array con #compact
Se un array ha uno o più elementi nil
e questi devono essere rimossi, l' Array#compact
o Array#compact!
i metodi possono essere utilizzati, come di seguito.
array = [ 1, nil, 'hello', nil, '5', 33]
array.compact # => [ 1, 'hello', '5', 33]
#notice that the method returns a new copy of the array with nil removed,
#without affecting the original
array = [ 1, nil, 'hello', nil, '5', 33]
#If you need the original array modified, you can either reassign it
array = array.compact # => [ 1, 'hello', '5', 33]
array = [ 1, 'hello', '5', 33]
#Or you can use the much more elegant 'bang' version of the method
array = [ 1, nil, 'hello', nil, '5', 33]
array.compact # => [ 1, 'hello', '5', 33]
array = [ 1, 'hello', '5', 33]
Infine, nota che se #compact
o #compact!
sono chiamati su un array senza elementi nil
, questi restituiranno zero.
array = [ 'foo', 4, 'life']
array.compact # => nil
array.compact! # => nil
Crea una matrice di numeri
Il modo normale per creare una serie di numeri:
numbers = [1, 2, 3, 4, 5]
Gli oggetti intervallo possono essere ampiamente utilizzati per creare una serie di numeri:
numbers = Array(1..10) # => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
numbers = (1..10).to_a # => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
#step
e #map
methods ci permettono di imporre condizioni sull'intervallo di numeri:
odd_numbers = (1..10).step(2).to_a # => [1, 3, 5, 7, 9]
even_numbers = 2.step(10, 2).to_a # => [2, 4, 6, 8, 10]
squared_numbers = (1..10).map { |number| number * number } # => [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
Tutti i metodi precedenti caricano i numeri con entusiasmo. Se devi caricarli pigramente:
number_generator = (1..100).lazy # => #<Enumerator::Lazy: 1..100>
number_generator.first(10) # => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Trasmetti l'array da qualsiasi oggetto
Per ottenere array da qualsiasi oggetto, usa Kernel#Array
.
Quanto segue è un esempio:
Array('something') #=> ["something"]
Array([2, 1, 5]) #=> [2, 1, 5]
Array(1) #=> [1]
Array(2..4) #=> [2, 3, 4]
Array([]) #=> []
Array(nil) #=> []
Ad esempio, è possibile sostituire il metodo join_as_string
dal seguente codice
def join_as_string(arg)
if arg.instance_of?(Array)
arg.join(',')
elsif arg.instance_of?(Range)
arg.to_a.join(',')
else
arg.to_s
end
end
join_as_string('something') #=> "something"
join_as_string([2, 1, 5]) #=> "2,1,5"
join_as_string(1) #=> "1"
join_as_string(2..4) #=> "2,3,4"
join_as_string([]) #=> ""
join_as_string(nil) #=> ""
al seguente codice
def join_as_string(arg)
Array(arg).join(',')
end