Вопрос по range, map, enumeration, ruby – Что делает метод «карта» в Ruby?

234

Я новичок в программировании. Может кто-нибудь объяснить, что.map будет делать в:

params = (0...param_count).map
REPL для ruby - это irb, для Rails - это rails c. REPL позволяет вам тестировать код непосредственно в самой языковой оболочке. Gary
Проситьone вопрос за один раз.map является общим «функциональным» метод, найденный в перечисляемых объектах, используемый для преобразования значений в последовательности (с особыми соображениями)... а также... способы создания диапазонов. Также,get familiar с REPL, где вы можете попробовать это самостоятельно! :) user166390

Ваш Ответ

6   ответов
61

map, вместе сselect а такжеeach это одна из рабочих лошадок Ruby в моем коде.

Это позволяет вам выполнить операцию с каждым из объектов вашего массива и вернуть их все в одном месте. Примером может быть увеличение массива чисел на единицу:

[1,2,3].map {|x| x + 1 }
#=> [2,3,4]

Если вы можете запустить один метод для элементов вашего массива, вы можете сделать это в стиле сокращения следующим образом:

To do this with the above example you'd have to do something like this

class Numeric
  def plusone
    self + 1
  end
end
[1,2,3].map(&:plusone)
#=> [2,3,4]

To more simply use the ampersand shortcut technique, let's use a different example:

["vanessa", "david", "thomas"].map(&:upcase)
#=> ["VANESSA", "DAVID", "THOMAS"]

Преобразование данных в Ruby часто включает каскадmap операции. Изучениеmap & Амп;selectони являются одними из самых полезных методов Ruby в первичной библиотеке. Они так же важны, какeach.

(map также псевдоним дляcollect, Используйте то, что лучше всего подходит для вас концептуально.)

More helpful information:

Еслиперечислимый объект, который вы запускаете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

В случае хэша (такжеEnumerable object, 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

To answer the actual question:

При условии, чтоparams является хэшем, это лучший способ отобразить его: используйте два параметра блока вместо одного, чтобы получить ключ & amp; пара значений для каждого интерпретируемого кортежа в хэше.

params = {"one" => 1, "two" => 2, "three" => 3}
params.each do |k,v|
  puts "#{k}=#{v}"
end
# one=1
# two=2
# three=3
@boulder_ruby, есть ли способ сделать это обычным методом & # x2014; как, а не метод класса?
хм звучит как ты объявилprivate внутри класса, где вы положили свой метод, прежде чем положить свой метод
Да, я просто поместил плохой пример в свой код, извините. Попробуйте модифицированный код. Это работает сейчас ...
Да, это так. За исключением того, что это не было. :( Во-первых, это был простой сценарий без классов, во-вторых, обычный irb. Вот моя копия / вставка вашего кода:gist.github.com/tjmcewan/a7e4feb2976a93a5eef9
Это не работает для меня в IRB. я получилNoMethodError: private method 'plusone' called for 1:Fixnum в ruby 2 и «неверное количество аргументов» в рубине 1.9 / 1.8. Во всяком случае, я использовал лямбду:plusone = ->(x) { x + 1 } затем возьмите спецификатор символа:[1,2,3].map(&plusone).
5

transform_valuesэта функция извлечена из рельсов в рубин.

h = {a: 1, b: 2, c: 3}

h.transform_values { |v| v * 10 }
 #=> {a: 10, b: 20, c: 30}
4

0..param_count 0...param_count означает «до, но не включая param_count».

Range#map не возвращаетEnumerable, это на самом деле отображает его в массив. Это так же, какRange#to_a.

2

Например:

  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}

Карта предоставляет значения, повторяющиеся в массиве, которые возвращаются параметрами блока.

Карта точно так же, как собирать.
415

map Метод принимает перечислимый объект и блок и запускает блок для каждого элемента, выводя каждое возвращаемое значение из блока (исходный объект остается неизменным, если вы не используетеmap!):

[1, 2, 3].

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 как будто это былоmap!
спасибо Сперанский за пример. тогда чем .map отличается от .each? Edmund
@ Inquisitive: «каждый»; возвращает массив, который вызывает его (в примере, [1,2,3]), когда предоставляется блок, 'map' apos; возвращает новый массив, заполненный значениями, рассчитанными блоком. Это может помочь: установите переменную ary = [1,2,3] и проверьте ее object_id. Затем запустите y = ary.each {| x | х + 1}; z = ary.map {| x | х + 1} Теперь проверьте object_id's для y и z. y имеет тот же object_id, что и ary (потому что каждый возвращает ary), но z имеет другой object_id, потому что map вернула новый массив.
чтобы увидеть разницу между картой и каждым, откройте окно IRB и посмотрите на результаты для y и z в следующем коде: y = [1,2,3] .each {| x | х + 1}; z = [1,2,3] .map {| x | х + 1}
Аааа, я понял. Таким образом, .map фактически изменяет массив, в то время как .each просто перебирает массив, чтобы получить доступ к значениям, оставляя исходный массив без изменений? Edmund
3

Enumerable - в этом случае диапазон. Поэтому он будет вызывать блок, переданный один раз для каждого целого числа от 0 доparam_count (исключая - вы правы относительно точек) и возвращаете массив, содержащий каждое возвращаемое значение.

Вот документация дляEnumerable#map. У него также есть псевдоним,collect.

Извините, я не знал, что карта, вызываемая сама по себе, не возвращаетEnumerableкак и у каждого. Я думал, что это сделал.
@PedroNascimento: Да ... это то, что я сказал?
Это странно, ноRange#map на самом деле преобразует его в массив.

Похожие вопросы