Это последняя статья в Руководстве по коллекциям Ruby. Я хочу закончить, предоставив несколько разных советов, которые, надеюсь, окажутся полезными во время ваших приключений с Ruby.
Более подробное создание массива
Во введении к массивам я показал вам, что вы можете заполнить массив значением по умолчанию, передав второй аргумент в Array.new
>> Array.new(3, 1)
=> [1,1,1]
Так что, если бы мы хотели инициализировать массив со случайными числами, мы могли бы просто передать вместо этого rand(x)
>> Array.new(3, rand(100))
=> [28,28,28]
Хм. Это было не совсем случайно. Похоже, что rand(100)
К счастью, Array#new
>> Array.new(3) { rand(100) }
=> [10,53,27]
Массовое задание
Подобно Python, Ruby позволяет присваивать более одной переменной или нескольким индексам в массиве в одном и том же операторе.
>> letter1, letter2 = ["a", "b"]
=> ["a", "b"]
>> letter1
=> "a"
>> letter2
=> "b"
>> transportation = []
>> transportation[0..1] = ["trains", "planes"]
>> transportation[0]
=> "trains"
>> transportation[1]
=> "planes"
Проверка границ
По умолчанию Ruby Arrays возвращает nil при отправке неверного индекса.
>> [1,2,3][99]
=> nil
Если вам не нравится это поведение (возможно, в ваших массивах много ноля), вы можете переопределить #[]
>> class Array
>> def [](idx)
>> self.fetch(idx)
>> end
>> end
>> [1,2,3][99]
=> IndexError: index 99 outside of array bounds: -3...3
!!ПРЕДУПРЕЖДЕНИЕ!! Обращение с основными библиотеками Ruby может привести к ошибкам, которые очень трудно отследить. Фактически, даже предыдущий пример убивает способность Array принимать более одного аргумента и, по-видимому, вызывает ошибки в irb. Если вы не хотите исследовать, как переопределить методы Array, не вызывая проблем, более безопасной альтернативой будет создание подкласса Array.
>> class BoundsCheckedArray < Array
>> def [](idx)
>> self.fetch(idx)
>> end
>> end
>> arr = BoundsCheckedArray.new([1,2,3])
>> arr[99]
=> IndexError: index 99 outside of array bounds: -3...3
Случайные элементы массива
Мы видели, как создавать случайные числа в Ruby, но что еще? Возможно, ваш значимый друг недавно реализовал такой метод:
>> def random_restaurant
>> "I don't care. Where do you want to go?"
>> end
>> 3.times.map { random_restaurant }
=> ["I don't care. Where do you want to go", "I don't care. Where do you want to go", "I don't care. Where do you want to go"]
Задушивая слезы разочарования, вы можете поместить в список несколько ресторанов поблизости и использовать метод #sample для случайного выбора .
>> def random_restaurant
>> ["Process: The Forkeria", "Shenanigans", "Grease Factory"].sample
>> end
>> 3.times.map { random_restaurant }
=> ["Process: The Forkeria", "Grease Factory", "Process: The Forkeria"]
Если вы дважды #sample
Если вам нужно более одного уникального случайного элемента, вы можете передать количество элементов в #sample.
>> ["a","b","c"].sample(2)
=> ["c", "a"]
Многомерные и высокопроизводительные массивы
В отличие от своего двоюродного брата Python, Ruby довольно хорошо позволяет вам объявлять многомерные массивы интуитивно понятным способом.
>> two_d = [[1,2,3],[4,5,6],[7,8,9]]
>> two_d[1][1]
=> 5
К сожалению, люди обычно не обращают внимания на Ruby при выполнении дорогостоящих математических операций. В этом случае часто намного легче покинуть корабль и изучить NumPy
Тем не менее, японский исследователь создал гем NArray, который предоставляет быстрые векторы и матрицы. К сожалению, цена скорости заключается в том, что вы ограничены однородными, числовыми коллекциями.
$ gem install narray --version 0.6.0.8
Создать n-мерные массивы с помощью NArray очень просто. Каждый аргумент конструктора NArray действует как размер для измерения.
>> require 'narray'
>> NArray.int(2)
=> NArray.int(2):
[ 0, 0 ]
>> NArray.int(2,2)
=> NArray.int(2,2):
[ [ 0, 0 ],
[ 0, 0 ] ]
>> NArray.int(2,3)
=> NArray.int(2,3):
[ [ 0, 0 ],
[ 0, 0 ],
[ 0, 0 ] ]
>> NArray.int(1,2)
=> NArray.int(1,2):
[ [ 0 ],
[ 0 ] ]
NArray использует обозначение [x, y] со вкусом математики вместо обозначения [x] [y] для указания индексов.
>> arr = NArray.int(3,3)
>> arr[1,1] = 7
>> arr
=> NArray.int(3,3):
[ [ 0, 0, 0 ],
[ 0, 7, 0 ],
[ 0, 0, 0 ] ]
Это не совместимо с массивом. arr[x][y]
>> arr[1][1]
=> 0
>> arr[1,1]
=> 7
Gem NArray не ограничивается целыми числами или объектами NArray. Английскую документацию по NArray можно найти здесь
Бенчмаркинг
С кажущимся бесконечным количеством способов доступа к коллекциям Ruby и манипулирования ими вам может быть интересно узнать, насколько эффективны используемые вами методы. Например, действительно ли быстрее выполнить тест членства с помощью Set, чем с Array?
Ruby предоставляет Benchmark для временного кода.
>> require "benchmark"
>> require "set"
>> array = ["a", -3.14, 0, []]
>> set = array.to_set
>> Benchmark.bm do |bench|
>> bench.report("array:") do
>> 1000.times { array.include? -3.14 }
>> end
>> bench.report("set:") do
>> 1000.times { set.include? -3.14 }
>> end
>> end
user system total real
array: 0.000000 0.000000 0.000000 ( 0.000200)
set: 0.000000 0.000000 0.000000 ( 0.000212)
Хотя это вряд ли можно назвать полным сравнением, разница для моей реализации Ruby кажется незначительной (1.9.3-p448).
Вывод
Ну вот и закончился мой сериал по коллекциям Ruby. Вот некоторые дополнительные ресурсы, если вы хотите продолжить свое образование: