Введение в Enumerables в Ruby

Enumerables — это методы Ruby, которые позволяют преобразовывать или иным образом работать с коллекциями объектов. Если вы хотите что-то сделать или получить ответы от массива или хэша, вы будете использовать перечисления.

Каждый

Базовый метод, из которого строятся перечисляемые, — это каждый. В некотором смысле каждое перечисляемое является частным случаем каждого. Вот как выглядит «каждый»:

example_array = ["what", "who", "chka-chka Slim Shady"]
example_array.each do |name|
   puts "My name is, #{name}"
end

Если мы запустим это, это даст нам:

My name is, what
My name is, who
My name is, chka-chka Slim Shady
=> ["what", "who", "chka-chka Slim Shady"]

Аккуратный! Мы видим, что мы что-то сделали с каждым из элементов нашего массива example_array. Давайте посмотрим на структуру этого оператора each.

example_array.each

Это синтаксис для вызова метода each для любого объекта — в данном случае массива с именем «example_array».

example_array.each do
end

Перечисления используют формат do-end. Мы говорим компьютеру: «Для каждого элемента примера массива сделайте любое указанное действие». А что за указанное?

example_array.each do
  puts "My name is, #{name}"
end

Для каждого элемента example_array мы хотим поместить строку «Меня зовут», за которой следует сам элемент. Мы делаем это, интерполируя элемент. Оставшаяся часть — это просто определение переменной, которую мы интерполируем:

example_array.each do |name|
  puts "My name is, #{name}"
end

Для тех, кто плохо знаком с перечислениями, это, вероятно, самая иностранная часть. Все, что мы здесь делаем, это говорим: «Для каждого члена примера массива установите этот член равным переменной ‘name’, а затем поместите ‘My name is, #{name}’».

Поскольку это всего лишь переменная, «имя» может быть любым. Мы назвали его «имя», чтобы нам было понятно, о чем мы говорим. Этот код точно такой же:

example_array.each do |x|
  puts "My name is, #{x)"
end

Наконец, я хочу упомянуть, что существует альтернативный способ записи перечислимых чисел. Вместо «do/end» можно использовать фигурные скобки. Преимущество этого заключается в том, что вы можете отличить свой перечислимый объект от любых других операторов типа «do/end», которые могут быть рядом с ним. Мы собираемся использовать это обозначение в оставшейся части этой статьи. Вот как это выглядит:

example_array.each{|name|
  puts "My name is, #{x}"
}

Или в одной строке:

example_array.each{|name| puts "My name is, #{x}"}

Что еще мы можем сделать с каждым? Много! Например, мы могли бы использовать условные операторы для проверки каждого элемента и, таким образом, найтиэлементы, удовлетворяющие определенным условиям. Мы могли бы использовать переменную, чтобы складывать элементы вместе. Мы могли бы проверить, верны ли определенные утверждения о массиве (или хеше). Но все эти вещи и многое другое можно сделать более наглядно и просто с помощью различных перечислимых методов.

Введение в Enumerables в Ruby

Мы собираемся начать рассматривать кучу различных перечислимых методов. Ваша цель здесь не должна состоять в том, чтобы запомнить их — просто посмотреть на них и понять, какие варианты у вас есть. Пока вы понимаете, что ищете, вы всегда можете найти их.

Все перечисления Ruby перечислены и подробно описаны в официальной документации Ruby. Эта страница просто предназначена для более удобного чтения для начинающих. Мы будем перечислять простые случаи только для того, чтобы проиллюстрировать логику каждого метода.

Если вы прокрутите вверх до нашего каждого примера, вы увидите, что хотя он напечатал то, что мы сказали, он просто вернул исходный массив . Если бы мы не сказали ему поместить что-нибудь, он бы вообще ничего для нас не сделал.

каждый уникален в этом отношении. Каждый другой перечислитель предназначен для возврата чего-то определенного.

Перечисления, возвращающие логическое значение

Есть пять перечислимых методов, которые просто возвращают «true» или «false»:

  • .все?
  • .нет?
  • .один?
  • .любой?
  • .include? / .член?

Их отличают вопросительные знаки, которых нет ни у одного другого счетчика. Может быть, вы можете начать представлять, что каждый из них делает, по его названию. Давайте используем массив чисел, чтобы проиллюстрировать, что они делают.

example_array = [1, 2, 3, 4]
example_array.all?{|number| number > 0} #=> true
example_array.all?{|number| number > 1} #=> false
example_array.all?{|number| number > 5} #=> false
example_array.none?{|number| number == 0} #=> true
example_array.none?{|number| number == 1} #=> false
example_array.one?{|number| number == 1} #=> true
example_array.one?{|number| number > 1} #=> false
example_array.any?{|number| number < 1} #=> false
example_array.any?{|number| number == 1} #=> true
example_array.any?{|number| number > 1} #=> true
example_array.include? 2 #=> true
example_array.include? 5 #=> false
example_array.include? "Doggy" #=> false

.include? и .member?являются синонимами. Они достаточно просты и не нуждаются в фигурных скобках — достаточно одного объекта, который спрашивает, включен ли он.

В Ruby все, кроме false и nil, является «истинным». Это может привести нас к таким сценариям:

example_array = [1, 2, 3, 4]
example_array.all? => true
example_array.none? => false
example_array.one? => false
example_array.any? => true
example_array = [1, 2, 3, nil]
example_array.all? => false
example_array.none? => false
example_array.one? => false
example_array.any? => true

В приведенных выше примерах мы не снабжали наши методы какими-либо блоками; они просто смотрят на достоверность каждого элемента в example_array.

Перечисления, возвращающие один из элементов

Эти методы обходят ваш массив или хэш и возвращают один из его элементов в соответствии с вашими спецификациями.

Точно так же, как каждый — это общий случай всех перечислимых, find — это общий случай всех перечислимых, которые ищут одно из значений в вашем массиве или хэше. обнаружить — это синоним слова найти.

На этот раз воспользуемся массивом строк.

example_array = ["Trains", "Planes", "Cranes", "Propane", "Automobiles", "etc."]
example_array.find{|vehicle| vehicle == "Planes"} #=> "Planes"
example_array.find{|vehicle| vehicle.length == 6} #=> "Trains"
example_array.find{|vehicle| vehicle.length > 6} #=> "Propane"

Вы могли заметить, что для последних двух запросов здесь было несколько элементов в example_array, которые удовлетворяли условию. Как findрешил, какой из них вернуть? Ну, он просто выбрал первое, в которое попал. Помните об этом всякий раз, когда используете эти методы.

example_array = ["Trains", "Planes", "Cranes", "Propane", "Automobiles", "etc."]
example_array.first #=> "Trains"
example_array.last #=> "etc."

Хорошо, достаточно просто.

example_array = ["Trains", "Planes", "Cranes", "Propane", "Automobiles", "etc."]
another_example = [3, 1, 4, 2]
example_array.min #=> "Trains"
another_example.min #=> 1
example_array.max #=> "etc."
another_example.max #=> 4

min и max ведут себя немного по-разному в зависимости от того, смотрят они на числа или нет. Если некоторые из элементов являются числами, а другие нет, они вообще не будут работать.

Возможно, вы ожидали, что min и max посмотрят на длину строк. Для этого — или любого другого атрибута нечисловых объектов — у нас есть min_by и max_by.

example_array = ["Trains", "Planes", "Cranes", "Propane", "Automobiles", "etc."]
example_array.min_by{|vehicle| vehicle.length} #=> "etc."
example_array.max_by{|vehicle| vehicle.length} #=> "Automobiles"

В следующем выпуске мы рассмотрим более сложные перечисления.