Eu sou novo em programação. Alguém pode explicar o .map
que faria em:
params = (0...param_count).map
Eu sou novo em programação. Alguém pode explicar o .map
que faria em:
params = (0...param_count).map
Respostas:
O map
método pega um objeto enumerável e um bloco e executa o bloco para cada elemento, produzindo cada valor retornado do bloco (o objeto original é inalterado, a menos que você use map!)
:
[1, 2, 3].map { |n| n * n } #=> [1, 4, 9]
Array
e Range
são tipos enumeráveis. map
com um bloco retorna uma matriz. map!
muda a matriz original.
Onde isso é útil e qual a diferença entre map!
e each
? Aqui está um exemplo:
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
A saída:
Danil is a programmer
Edmund is a programmer
map
como se fossemap!
map
, junto com select
e each
é um dos cavalos de trabalho de Ruby no meu código.
Permite executar uma operação em cada um dos objetos da sua matriz e devolvê-los todos no mesmo local. Um exemplo seria incrementar uma matriz de números em um:
[1,2,3].map {|x| x + 1 }
#=> [2,3,4]
Se você pode executar um único método nos elementos da sua matriz, pode fazê-lo em um estilo abreviado, como segue:
Para fazer isso com o exemplo acima, você teria que fazer algo assim
class Numeric
def plusone
self + 1
end
end
[1,2,3].map(&:plusone)
#=> [2,3,4]
Para usar mais simplesmente a técnica de atalho "e comercial", vamos usar um exemplo diferente:
["vanessa", "david", "thomas"].map(&:upcase)
#=> ["VANESSA", "DAVID", "THOMAS"]
A transformação de dados no Ruby geralmente envolve uma cascata de map
operações. Study map
& select
, eles são alguns dos métodos Ruby mais úteis na biblioteca principal. Eles são tão importantes quanto each
.
( map
também é um apelido para collect
. Use o que for melhor para você conceitualmente.)
Informações mais úteis:
Se o objeto Enumerable em que você estiver executando each
ou map
contiver um conjunto de elementos Enumerable (hashes, matrizes), você poderá declarar cada um desses elementos dentro de seus tubos de bloco da seguinte maneira:
[["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
No caso de um Hash (também um Enumerable
objeto, um Hash é simplesmente uma matriz de tuplas com instruções especiais para o intérprete). O primeiro "parâmetro do tubo" é a chave, o segundo é o valor.
{:make => "audi", :color => "black", :year => 2008}.each do |k,v|
puts "#{k} is #{v}"
end
#make is audi
#color is black
#year is 2008
Para responder à pergunta real:
Supondo que params
seja um hash, essa seria a melhor maneira de mapear através dele: use dois parâmetros de bloco em vez de um para capturar o par de chave e valor para cada tupla interpretada no hash.
params = {"one" => 1, "two" => 2, "three" => 3}
params.each do |k,v|
puts "#{k}=#{v}"
end
# one=1
# two=2
# three=3
NoMethodError: private method 'plusone' called for 1:Fixnum
no ruby 2 e 'número errado de args' no ruby 1.9 / 1.8. De qualquer forma, eu usei um lambda: plusone = ->(x) { x + 1 }
seguida, retire o símbolo especificador: [1,2,3].map(&plusone)
.
private
dentro da classe onde você colocar o seu método antes de você colocar o seu método
0..param_count
significa "até e incluindo param_count".
0...param_count
significa "até, mas não incluindo param_count".
Range#map
não retorna um Enumerable
, na verdade ele mapeia para uma matriz. É o mesmo que Range#to_a
.
Ele "mapeia" uma função para cada item em um Enumerable
- nesse caso, um intervalo. Portanto, chamaria o bloco passado uma vez para cada número inteiro de 0 a param_count
(exclusivo - você está certo sobre os pontos) e retornaria uma matriz contendo cada valor de retorno.
Aqui está a documentação para Enumerable#map
. Também possui um alias collect
,.
Range#map
na verdade converte para uma matriz.
Enumerable
, como cada um. Eu pensei que sim.
O mapa é uma parte do módulo enumerável. Muito parecido com "collect". Por exemplo:
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}
O mapa fornece valores iterativos por meio de uma matriz retornada pelos parâmetros do bloco.
#each
#each
executa uma função para cada elemento em uma matriz. Os dois trechos de código a seguir são equivalentes:
x = 10
["zero", "one", "two"].each{|element|
x++
puts element
}
x = 10
array = ["zero", "one", "two"]
for i in 0..2
x++
puts array[i]
end
#map
#map
aplica uma função a cada elemento de uma matriz, retornando a matriz resultante. Os seguintes são equivalentes:
array = ["zero", "one", "two"]
newArray = array.map{|element| element.capitalize()}
array = ["zero", "one", "two"]
newArray = []
array.each{|element|
newArray << element.capitalize()
}
#map!
#map!
é como #map
, mas modifica a matriz no lugar. Os seguintes são equivalentes:
array = ["zero", "one", "two"]
array.map!{|element| element.capitalize()}
array = ["zero", "one", "two"]
array = array.map{|element| element.capitalize()}
map
é um método "funcional" comum encontrado em objetos enumeráveis usados para transformar os valores em uma sequência (com considerações especiais)...
e...
são maneiras de criar intervalos. Além disso, familiarize-se com o REPL, onde você pode experimentar você mesmo! :)