Ruby Language
Tablice
Szukaj…
Składnia
- a = [] # używając literału tablicowego
- a = Array.new # równoważne użyciu literału
- a = Array.new (5) # utwórz tablicę z 5 elementami o wartości zero.
- a = Array.new (5, 0) # utwórz tablicę z 5 elementami o domyślnej wartości 0.
#mapa
#map
, dostarczone przez Enumerable, tworzy tablicę, wywołując blok na każdym elemencie i zbierając wyniki:
[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]
Oryginalna tablica nie jest modyfikowana; zwracana jest nowa tablica zawierająca przekształcone wartości w tej samej kolejności co wartości źródłowe. map!
można użyć, jeśli chcesz zmodyfikować oryginalną tablicę.
W metodzie map
można wywołać metodę lub użyć proc do wszystkich elementów w tablicy.
# 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
jest synonimem collect
.
Tworzenie tablicy za pomocą dosłownego konstruktora []
Tablice można tworzyć, umieszczając listę elementów w nawiasach kwadratowych ( [
i ]
). Elementy tablicy w tej notacji są oddzielone przecinkami:
array = [1, 2, 3, 4]
Tablice mogą zawierać dowolne obiekty w dowolnej kombinacji bez ograniczeń typu:
array = [1, 'b', nil, [3, 4]]
Utwórz tablicę ciągów
Tablice ciągów znaków można tworzyć przy użyciu składni procentowej ciągu ruby:
array = %w(one two three four)
Jest to funkcjonalnie równoważne zdefiniowaniu tablicy jako:
array = ['one', 'two', 'three', 'four']
Zamiast %w()
możesz użyć innych pasujących par ograniczników: %w{...}
, %w[...]
lub %w<...>
.
Możliwe jest również użycie dowolnych niealfanumerycznych ograniczników, takich jak: %w!...!
, %w#...#
lub %w@...@
.
Można użyć %W
zamiast %w
do włączenia interpolacji łańcucha. Rozważ następujące:
var = 'hello'
%w(#{var}) # => ["\#{var}"]
%W(#{var}) # => ["hello"]
Wiele słów można interpretować, uciekając spacją za pomocą \.
%w(Colorado California New\ York) # => ["Colorado", "California", "New York"]
Utwórz tablicę symboli
array = %i(one two three four)
Tworzy tablicę [:one, :two, :three, :four]
.
Zamiast %i(...)
możesz użyć %i{...}
lub %i[...]
lub %i!...!
Dodatkowo, jeśli chcesz użyć interpolacji, możesz to zrobić za pomocą %I
a = 'hello'
b = 'goodbye'
array_one = %I(#{a} #{b} world)
array_two = %i(#{a} #{b} world)
Tworzy tablice: array_one = [:hello, :goodbye, :world]
array_two = [:"\#{a}", :"\#{b}", :world]
array_one = [:hello, :goodbye, :world]
and array_two = [:"\#{a}", :"\#{b}", :world]
Utwórz tablicę za pomocą Array :: new
Pusty Array ( []
) można utworzyć za pomocą metody klasy Array::new
, Array::new
:
Array.new
Aby ustawić długość tablicy, przekaż argument liczbowy:
Array.new 3 #=> [nil, nil, nil]
Istnieją dwa sposoby zapełnienia tablicy wartościami domyślnymi:
- Przekaż niezmienną wartość jako drugi argument.
- Przekaż blok, który pobiera bieżący indeks i generuje zmienne wartości.
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"]
Manipulowanie elementami macierzy
Dodawanie elementów:
[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]]
Usuwanie elementów:
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
Łączenie tablic:
[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]
Możesz także pomnożyć tablice, np
[1, 2, 3] * 2
# => [1, 2, 3, 1, 2, 3]
Tablica unii, przecięcia i różnicy
x = [5, 5, 1, 3]
y = [5, 2, 4, 3]
Unia ( |
) zawiera elementy z obu tablic, z usuniętymi duplikatami:
x | y
=> [5, 1, 3, 2, 4]
Przecięcie ( &
) zawiera elementy, które są obecne zarówno w pierwszej, jak i drugiej tablicy:
x & y
=> [5, 3]
Różnica ( -
) zawiera elementy, które są obecne w pierwszej tablicy i nie występują w drugiej tablicy:
x - y
=> [1]
Filtrowanie tablic
Często chcemy operować tylko na elementach tablicy, które spełniają określony warunek:
Wybierz
Zwróci elementy pasujące do określonego warunku
array = [1, 2, 3, 4, 5, 6]
array.select { |number| number > 3 } # => [4, 5, 6]
Odrzucać
Zwróci elementy, które nie pasują do określonego warunku
array = [1, 2, 3, 4, 5, 6]
array.reject { |number| number > 3 } # => [1, 2, 3]
Zarówno #select
jak i #reject
zwracają tablicę, dzięki czemu można je łączyć:
array = [1, 2, 3, 4, 5, 6]
array.select { |number| number > 3 }.reject { |number| number < 5 }
# => [5, 6]
Wstrzyknąć, zmniejszyć
Wstrzykiwanie i zmniejszanie to różne nazwy dla tej samej rzeczy. W innych językach funkcje te są często nazywane fałdami (np. Foldl lub foldr). Te metody są dostępne dla każdego obiektu Enumerable.
Wtrysk przyjmuje funkcję dwóch argumentów i stosuje ją do wszystkich par elementów w tablicy.
Do tablicy [1, 2, 3]
możemy dodać je wszystkie wraz z wartością początkową zero, określając wartość początkową i blok w następujący sposób:
[1,2,3].reduce(0) {|a,b| a + b} # => 6
Tutaj przekazujemy funkcji wartość początkową i blok, który mówi, aby dodać wszystkie wartości razem. Blok jest najpierw uruchamiany z 0
jako a
i 1
jako b
, a następnie przyjmuje wynik tego jako następny a
więc dodajemy 1
do drugiej wartości 2
. Następnie bierzemy wynik tego ( 3
) i dodajemy go do ostatniego elementu na liście (również 3
), podając nasz wynik ( 6
).
Jeśli pominiemy pierwszy argument, ustawi a
jako pierwszy element na liście, więc powyższy przykład jest taki sam jak:
[1,2,3].reduce {|a,b| a + b} # => 6
Ponadto zamiast przekazywać blok z funkcją, możemy przekazać nazwaną funkcję jako symbol, albo z wartością początkową, albo bez. Dzięki temu powyższy przykład można zapisać jako:
[1,2,3].reduce(0, :+) # => 6
lub pomijając wartość początkową:
[1,2,3].reduce(:+) # => 6
Dostęp do elementów
Możesz uzyskać dostęp do elementów tablicy według ich indeksów. Numeracja indeksu tablicy zaczyna się od 0
.
%w(a b c)[0] # => 'a'
%w(a b c)[1] # => 'b'
Możesz przyciąć tablicę za pomocą zasięgu
%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)
Zwraca nową tablicę, ale nie wpływa na oryginał. Ruby obsługuje również stosowanie ujemnych wskaźników.
%w(a b c)[-1] # => 'c'
%w(a b c)[-2] # => 'b'
Możesz także łączyć wskaźniki ujemne i dodatnie
%w(a b c d e)[1...-1] # => ['b', 'c', 'd']
Inne przydatne metody
Użyj first
aby uzyskać dostęp do pierwszego elementu w tablicy:
[1, 2, 3, 4].first # => 1
Lub first(n)
aby uzyskać dostęp do pierwszych n
elementów zwróconych w tablicy:
[1, 2, 3, 4].first(2) # => [1, 2]
Podobnie dla last
i last(n)
:
[1, 2, 3, 4].last # => 4
[1, 2, 3, 4].last(2) # => [3, 4]
Użyj sample
aby uzyskać dostęp do losowego elementu w tablicy:
[1, 2, 3, 4].sample # => 3
[1, 2, 3, 4].sample # => 1
Lub sample(n)
:
[1, 2, 3, 4].sample(2) # => [2, 1]
[1, 2, 3, 4].sample(2) # => [3, 4]
Tablica dwuwymiarowa
Korzystając z konstruktora Array::new
, możesz zainicjować tablicę o danym rozmiarze i nową tablicę w każdym z jej gniazd. Wewnętrzne tablice mogą mieć również rozmiar i wartość początkową.
Na przykład, aby utworzyć tablicę zer 3x4:
array = Array.new(3) { Array.new(4) { 0 } }
Tablica wygenerowana powyżej wygląda tak po wydrukowaniu za pomocą p
:
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
Możesz czytać lub pisać do takich elementów:
x = array[0][1]
array[2][3] = 2
Tablice i operator splat (*)
Za pomocą operatora *
można rozpakować zmienne i tablice, aby można je było przekazywać jako indywidualne argumenty do metody.
Można tego użyć do zawinięcia pojedynczego obiektu w tablicy, jeśli nie jest on jeszcze:
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)
#> []
W powyższym przykładzie metoda wrap_in_array
przyjmuje jeden argument, value
.
Jeśli value
jest Array
, jej elementy są rozpakowywane i tworzona jest nowa tablica zawierająca ten element.
Jeśli value
jest pojedynczym obiektem, tworzona jest nowa tablica zawierająca ten pojedynczy obiekt.
Jeśli value
wynosi nil
, value
jest pusta tablica.
Operator splat jest szczególnie przydatny, gdy w niektórych przypadkach jest wykorzystywany jako argument w metodach. Na przykład, umożliwia nil
, pojedyncze wartości i macierze mają być obsługiwane w zgodny sposób:
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
Rozkład
Dowolną tablicę można szybko rozłożyć , przypisując jej elementy do wielu zmiennych. Prosty przykład:
arr = [1, 2, 3]
# ---
a = arr[0]
b = arr[1]
c = arr[2]
# --- or, the same
a, b, c = arr
Poprzedzenie zmiennej operatorem splat ( *
) wstawia do niej tablicę wszystkich elementów, które nie zostały przechwycone przez inne zmienne. Jeśli nie ma żadnych, przypisywana jest pusta tablica. W jednym zadaniu można użyć tylko jednej ikony:
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 *
Rozkład jest bezpieczny i nigdy nie powoduje błędów. nil
jest przypisywane tam, gdzie nie ma wystarczającej liczby elementów, pasujących do zachowania operatora []
podczas uzyskiwania dostępu do indeksu poza granicami:
arr[9000] # => nil
a, b, c, d = arr # a = 1; b = 2; c = 3; d = nil
Dekompozycja próbuje niejawnie wywołać to_ary
na przypisywanym obiekcie. Wdrażając tę metodę w swoim typie, zyskujesz możliwość jej rozkładu:
class Foo
def to_ary
[1, 2]
end
end
a, b = Foo.new # a = 1; b = 2
Jeśli rozkładany obiekt nie respond_to?
to_ary
, jest traktowany jako tablica jednoelementowa:
1.respond_to?(:to_ary) # => false
a, b = 1 # a = 1; b = nil
Dekompozycję można również zagnieżdżać , używając wyrażenia dekompozycji ograniczonego ()
zamiast tego, co w innym przypadku byłoby pojedynczym elementem:
arr = [1, [2, 3, 4], 5, 6]
a, (b, *c), *d = arr # a = 1; b = 2; c = [3, 4]; d = [5, 6]
# ^^^^^
Jest to faktycznie przeciwieństwo splat .
Właściwie każde wyrażenie dekompozycji może być rozdzielane przez ()
. Ale dla pierwszego poziomu rozkład jest opcjonalny.
a, b = [1, 2]
(a, b) = [1, 2] # the same thing
Przypadek krawędzi: pojedynczego identyfikatora nie można użyć jako wzorca destrukcji, zewnętrznego lub zagnieżdżonego:
(a) = [1] # SyntaxError
a, (b) = [1, [2]] # SyntaxError
Przypisując literał tablicowy do wyrażenia destrukcyjnego, external []
można pominąć:
a, b = [1, 2]
a, b = 1, 2 # exactly the same
Jest to znane jako przypisanie równoległe , ale wykorzystuje ten sam rozkład pod maską. Jest to szczególnie przydatne do wymiany wartości zmiennych bez stosowania dodatkowych zmiennych tymczasowych:
t = a; a = b; b = t # an obvious way
a, b = b, a # an idiomatic way
(a, b) = [b, a] # ...and how it works
Wartości są przechwytywane podczas budowania prawej strony zadania, więc użycie tych samych zmiennych co źródło i miejsce docelowe jest względnie bezpieczne.
Zamień tablicę wielowymiarową w tablicę jednowymiarową (spłaszczoną)
[1, 2, [[3, 4], [5]], 6].flatten # => [1, 2, 3, 4, 5, 6]
Jeśli masz tablicę wielowymiarową i musisz uczynić ją prostą (tj. Jednowymiarową) tablicą, możesz użyć metody #flatten
.
Uzyskaj unikalne elementy tablicy
Jeśli chcesz odczytać elementy tablicy unikając powtórzeń , użyj metody #uniq
:
a = [1, 1, 2, 3, 4, 4, 5]
a.uniq
#=> [1, 2, 3, 4, 5]
Zamiast tego, jeśli chcesz usunąć wszystkie zduplikowane elementy z tablicy, możesz użyć #uniq!
metoda:
a = [1, 1, 2, 3, 4, 4, 5]
a.uniq!
#=> [1, 2, 3, 4, 5]
Chociaż wynik jest taki sam, #uniq!
przechowuje również nową tablicę:
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]
Uzyskaj wszystkie kombinacje / permutacje tablicy
Metoda permutation
, wywołana z blokiem, daje dwuwymiarową tablicę składającą się ze wszystkich uporządkowanych sekwencji zbioru liczb.
Jeśli ta metoda zostanie wywołana bez bloku, zwróci enumerator
. Aby przekonwertować na tablicę, wywołaj metodę to_a
.
Przykład | Wynik |
---|---|
[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 | [] -> Brak permutacji o długości 4 |
Z drugiej strony metoda combination
wywołana blokiem daje dwuwymiarową tablicę składającą się ze wszystkich sekwencji zbioru liczb. W przeciwieństwie do permutacji, porządek jest pomijany w kombinacjach. Na przykład [1,2,3]
jest taki sam jak [3,2,1]
Przykład | Wynik |
---|---|
[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 | [] -> Brak kombinacji długości 4 |
Samo wywołanie metody kombinacji spowoduje wyliczenie. Aby uzyskać tablicę, wywołaj metodę to_a
.
Metody repeated_combination
i repeated_permutation
są podobne, z tym wyjątkiem, że ten sam element można powtórzyć wiele razy.
Na przykład sekwencje [1,1]
, [1,3,3,1]
, [3,3,3]
nie byłyby prawidłowe w regularnych kombinacjach i permutacjach.
Przykład | # Kombinacje |
---|---|
[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 |
Utwórz tablicę kolejnych cyfr lub liter
Można to łatwo osiągnąć, wywołując Enumerable#to_a
na obiekcie Range
:
(1..10).to_a #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
(a..b)
oznacza, że będzie zawierać wszystkie liczby od a do b. Aby wykluczyć ostatni numer, użyj a...b
a_range = 1...5
a_range.to_a #=> [1, 2, 3, 4]
lub
('a'..'f').to_a #=> ["a", "b", "c", "d", "e", "f"]
('a'...'f').to_a #=> ["a", "b", "c", "d", "e"]
Wygodnym skrótem do tworzenia tablicy jest [*a..b]
[*1..10] #=> [1,2,3,4,5,6,7,8,9,10]
[*'a'..'f'] #=> ["a", "b", "c", "d", "e", "f"]
Usuń wszystkie elementy zerowe z tablicy za pomocą #compact
Jeśli tablica zawiera jeden lub więcej elementów nil
i należy je usunąć, Array#compact
lub Array#compact!
metody mogą być stosowane, jak poniżej.
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]
Na koniec zauważ, że jeśli #compact
lub #compact!
są wywoływane w tablicy bez elementów nil
, zwracają zero.
array = [ 'foo', 4, 'life']
array.compact # => nil
array.compact! # => nil
Utwórz tablicę liczb
Normalny sposób tworzenia tablicy liczb:
numbers = [1, 2, 3, 4, 5]
Obiekty zakresu mogą być szeroko stosowane do tworzenia tablicy liczb:
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
i #map
pozwalają nam nałożyć warunki na zakres liczb:
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]
Wszystkie powyższe metody chętnie ładują liczby. Jeśli musisz je ładować leniwie:
number_generator = (1..100).lazy # => #<Enumerator::Lazy: 1..100>
number_generator.first(10) # => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Rzucaj na Array z dowolnego obiektu
Aby uzyskać tablicę z dowolnego obiektu, użyj Kernel#Array
.
Oto przykład:
Array('something') #=> ["something"]
Array([2, 1, 5]) #=> [2, 1, 5]
Array(1) #=> [1]
Array(2..4) #=> [2, 3, 4]
Array([]) #=> []
Array(nil) #=> []
Na przykład możesz zastąpić metodę join_as_string
z następującego kodu
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) #=> ""
do następującego kodu.
def join_as_string(arg)
Array(arg).join(',')
end