Я новичок в программировании. Может кто-нибудь объяснить, что .map
будет делать в:
params = (0...param_count).map
Я новичок в программировании. Может кто-нибудь объяснить, что .map
будет делать в:
params = (0...param_count).map
Метод map
принимает перечислимый объект и блок и запускает блок для каждого элемента, выводя каждое возвращаемое значение из блока (исходный объект не изменяется, если вы не используете map!)
:
[1, 2, 3].map { |n| n * n } #=> [1, 4, 9]
Array
и Range
являются перечисляемыми типами. map
с блоком возвращает массив. map!
мутирует исходный массив.
Где это полезно, и в чем разница между map!
и each
? Вот пример:
names = ['danil', 'edmund']
# here we map one array to another, convert each element by some rule
names.map! {|name| name.capitalize } # now names contains ['Danil', 'Edmund']
names.each { |name| puts name + ' is a programmer' } # here we just do something with each element
Выход:
Danil is a programmer
Edmund is a programmer
map
, наряду с select
и each
является одним из рабочих лошадей Ruby в моем коде.
Он позволяет запускать операцию над каждым из ваших объектов массива и возвращать их все в одном месте. Примером может быть увеличение массива чисел на единицу:
[1,2,3].map {|x| x + 1 }
#=> [2,3,4]
Если вы можете запустить один метод в своих элементах массива, вы можете сделать это в стенографическом стиле:
Чтобы сделать это с помощью приведенного выше примера, вам нужно сделать что-то вроде этого
class Numeric
def plusone
self + 1
end
end
[1,2,3].map(&:plusone)
#=> [2,3,4]
Чтобы более просто использовать технику ярлыка амперсанда, используйте другой пример:
["vanessa", "david", "thomas"].map(&:upcase)
#=> ["VANESSA", "DAVID", "THOMAS"]
Преобразование данных в Ruby часто связано с каскадом операций map
. Изучите map
и select
, они являются одними из наиболее полезных методов Ruby в основной библиотеке. Они так же важны, как each
.
(map
также является псевдонимом для collect
). Используйте все, что лучше всего подходит для вас концептуально.)
Дополнительная информация:
Если объект Enumerable, на котором вы работаете each
или map
on, содержит набор элементов Enumerable (хэши, массивы), вы можете объявить каждый из этих элементов внутри ваших блоков так:
[["audi", "black", 2008], ["bmw", "red", 2014]].each do |make, color, year|
puts "make: #{make}, color: #{color}, year: #{year}"
end
# Output:
# make: audi, color: black, year: 2008
# make: bmw, color: red, year: 2014
В случае объекта Hash (также объект Enumerable
, Hash - это просто массив кортежей со специальными инструкциями для интерпретатора). Первый "параметр трубы" - это ключ, второй - значение.
{:make => "audi", :color => "black", :year => 2008}.each do |k,v|
puts "#{k} is #{v}"
end
#make is audi
#color is black
#year is 2008
Чтобы ответить на реальный вопрос:
Предполагая, что params
является хешем, это лучший способ его отображения: используйте два параметра блока вместо одного, чтобы захватить пару ключей и значений для каждого интерпретированного кортежа в хеше.
params = {"one" => 1, "two" => 2, "three" => 3}
params.each do |k,v|
puts "#{k}=#{v}"
end
# one=1
# two=2
# three=3
0..param_count
означает "до и включая param_count".
0...param_count
означает "до, но не включая param_count".
Range#map
не возвращает Enumerable
, он фактически сопоставляет его с массивом. Это то же самое, что и Range#to_a
.
Он "отображает" функцию для каждого элемента в Enumerable
- в этом случае диапазон. Таким образом, он будет вызывать блок, переданный один раз для каждого целого числа от 0 до param_count
(исключая - вы правы относительно точек) и возвращаете массив, содержащий каждое возвращаемое значение.
Здесь документация для Enumerable#map
. У него также есть псевдоним collect
.
Я попробую другой способ объяснения выше:
Что делает карта
Раньше я работал в папке с копией фотографий в тот же день. Нам дали стопку бумаг. И в основном нам приходилось:
Другими словами, нам дали определенные страницы, которые нам пришлось преобразовать во что-то новое. В этом случае конечным результатом была фотокопия с новым штампом на них.
Я мог бы просто легко: (i) отредактировать первую строку или (ii) полностью уничтожить новую ксерокопию.
Это в основном то, что делает функция карты: она позволяет вам преобразовывать ряд элементов во что угодно!
basket = [apple, orange, banana]
new_basket_full_of_eaten_food = basket.map { |food_item| food_item.take_a_huge_bite }
В приведенном выше случае мы превратили корзину продуктов в новую корзину с огромным укусом в каждом из фруктов. То, как оно преобразилось!
Внимание!
Как примечания @Anthony ниже, исходная корзина фруктов остается неприкасаемой: она все еще там, и там нет укусов.
Вы можете подтвердить это в рубиновой документации здесь: https://ruby-doc.org/core-2.2.0/Array.html#method-i-map
Надеюсь, это поможет вам.
Используя ruby 2.4, вы можете сделать то же самое с помощью transform_values
, эта функция извлекается из рельсов в ruby.
h = {a: 1, b: 2, c: 3}
h.transform_values { |v| v * 10 }
#=> {a: 10, b: 20, c: 30}
Карта является частью перечислимого модуля. Очень похоже на "собирать" Пример:
Class Car
attr_accessor :name, :model, :year
Def initialize (make, model, year)
@make, @model, @year = make, model, year
end
end
list = []
list << Car.new("Honda", "Accord", 2016)
list << Car.new("Toyota", "Camry", 2015)
list << Car.new("Nissan", "Altima", 2014)
p list.map {|p| p.model}
Карта предоставляет значения, повторяющиеся через массив, возвращаемый параметрами блока.