Ruby Language
итерация
Поиск…
каждый
Ruby имеет много типов счетчиков, но первый и самый простой тип перечислителя для начала - это each . Мы будем печатать even или odd для каждого номера от 1 до 10 чтобы показать, как each работает.
В принципе есть два способа передать так называемые blocks . block представляет собой часть передаваемого кода, которая будет выполняться вызываемым методом. each метод принимает block который он вызывает для каждого элемента коллекции объектов, на который он был вызван.
Существует два способа передать блок методу:
Способ 1: встроенный
(1..10).each { |i| puts i.even? ? 'even' : 'odd' }
Это очень сжатый и рубиновый способ решить эту проблему. Давайте разложим это по частям.
-
(1..10)представляет собой диапазон от1до10включительно. Если бы мы хотели, чтобы это было от1до10эксклюзивных, мы писали бы(1...10). -
.each- перечислитель, который перечисляетeachэлемент в объекте, на котором он действует. В этом случае он действует наeachчисло в диапазоне. -
{ |i| puts i.even? ? 'even' : 'odd' }является блоком дляeachутверждения, которое само по себе можно разбить дальше.-
|i|это означает, что каждый элемент в диапазоне представлен внутри блока идентификаторомi. -
puts- это метод вывода в Ruby с автоматическим прерыванием строки после каждого его распечатывания. (Мы можем использоватьprintесли мы не хотим, чтобы автоматический разрыв строки) -
i.even?проверяет, четный лиi. Мы могли бы также использоватьi % 2 == 0; однако предпочтительнее использовать встроенные методы. -
? "even" : "odd"- это тернарный оператор рубина. То, как построен тернарный оператор, являетсяexpression ? a : b. Это коротко для
if expression a else b end
-
Для кода длиной более одной строки block должен быть передан как multiline block .
Способ 2: Многострочный
(1..10).each do |i|
if i.even?
puts 'even'
else
puts 'odd'
end
end
В multiline block do заменяет открывающий кронштейн и end заменяет закрывающий кронштейн из inline стиля.
Ruby поддерживает reverse_each. Он будет перебирать массив назад.
@arr = [1,2,3,4]
puts @arr.inspect # output is [1,2,3,4]
print "Reversed array elements["
@arr.reverse_each do |val|
print " #{val} " # output is 4 3 2 1
end
print "]\n"
Внедрение в классе
Enumerable - самый популярный модуль в Ruby. Его цель - предоставить вам итеративные методы, такие как map , select , reduce и т. Д. Классы, которые используют Enumerable включают Array , Hash , Range . Чтобы использовать его, вы должны include Enumerable и реализовать each .
class NaturalNumbers
include Enumerable
def initialize(upper_limit)
@upper_limit = upper_limit
end
def each(&block)
0.upto(@upper_limit).each(&block)
end
end
n = NaturalNumbers.new(6)
n.reduce(:+) # => 21
n.select(&:even?) # => [0, 2, 4, 6]
n.map { |number| number ** 2 } # => [0, 1, 4, 9, 16, 25, 36]
карта
Возвращает измененный объект, но исходный объект остается таким, какой он есть. Например:
arr = [1, 2, 3]
arr.map { |i| i + 1 } # => [2, 3, 4]
arr # => [1, 2, 3]
map! изменяет исходный объект:
arr = [1, 2, 3]
arr.map! { |i| i + 1 } # => [2, 3, 4]
arr # => [2, 3, 4]
Примечание. Вы также можете использовать collect для выполнения той же самой вещи.
Итерация по сложным объектам
Массивы
Вы можете выполнять итерацию по вложенным массивам:
[[1, 2], [3, 4]].each { |(a, b)| p "a: #{ a }", "b: #{ b }" }
Также допускается следующий синтаксис:
[[1, 2], [3, 4]].each { |a, b| "a: #{ a }", "b: #{ b }" }
Будет производить:
"a: 1"
"b: 2"
"a: 3"
"b: 4"
Хэш
Вы можете перебирать пары ключ-значение:
{a: 1, b: 2, c: 3}.each { |pair| p "pair: #{ pair }" }
Будет производить:
"pair: [:a, 1]"
"pair: [:b, 2]"
"pair: [:c, 3]"
Вы можете перебирать ключи и значения одновременно:
{a: 1, b: 2, c: 3}.each { |(k, v)| p "k: #{ k }", "v: #{ k }" }
Будет производить:
"k: a"
"v: a"
"k: b"
"v: b"
"k: c"
"v: c"
Для итератора
Это повторяется от 4 до 13 (включительно).
for i in 4..13
puts "this is #{i}.th number"
end
Мы также можем перебирать массивы, используя для
names = ['Siva', 'Charan', 'Naresh', 'Manish']
for name in names
puts name
end
Итерация с индексом
Иногда вы хотите знать позицию ( индекс ) текущего элемента во время итерации над перечислителем. Для этой цели Ruby предоставляет метод with_index . Он может применяться ко всем счетчикам. В принципе, добавив with_index к перечислению, вы можете перечислить это перечисление. Индекс передается блоку в качестве второго аргумента.
[2,3,4].map.with_index { |e, i| puts "Element of array number #{i} => #{e}" }
#Element of array number 0 => 2
#Element of array number 1 => 3
#Element of array number 2 => 4
#=> [nil, nil, nil]
with_index имеет необязательный аргумент - первый индекс, который по умолчанию равен 0 :
[2,3,4].map.with_index(1) { |e, i| puts "Element of array number #{i} => #{e}" }
#Element of array number 1 => 2
#Element of array number 2 => 3
#Element of array number 3 => 4
#=> [nil, nil, nil]
Существует специальный метод each_with_index . Единственное различие между ним и each.with_index заключается в том, что вы не можете передать аргумент этому, поэтому первый индекс равен 0 все время.
[2,3,4].each_with_index { |e, i| puts "Element of array number #{i} => #{e}" }
#Element of array number 0 => 2
#Element of array number 1 => 3
#Element of array number 2 => 4
#=> [2, 3, 4]