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]