Conhecendo os métodos .map, .collect e .pluck

Um bom programador, dentre outras coisas, é aquele que conhece todas as nuances e atalhos da linguagem de programação que está usando, não é mesmo? 🙂 Sendo assim, vamos conhecer um pouco mais sobre esses três métodos.

Antes de conhecermos os métodos citados no título desse post, vamos imaginar a seguinte situação. Temos um Array [1,2,3,4,5] e queremos criar um algoritmo que ao final nos devolva um novo Array com o dobro de cada item do Array informado. Ou seja, informamos [1,2,3,4,5] e ao final teremos [2,4,6,8,10].

Pois bem, da forma convencional e mais simples possível podemos fazer assim…

a = [1,2,3,4,5]
b = []
a.each do |i|
b.push(i*2)
end
#=> b
[2,4,6,8,10]

Prontinho. Dessa forma teremos um segundo Array (b) que conterá o resultado esperado, no entanto isso traz um problema que é ter que declarar um Array (b) apenas para armazenar o resultado esperado.

Para resolver problemas como esse podemos nos utilizar do método .map

.map

O método .map, conforme documentação — “Cria um novo Array contendo os valores retornados pelo bloco — , ou seja, ele recebe uma “coleção/enumerable” (Arrays, Hashes, resultados do ActiveRecord) e ao final devolve um Array de acordo com o bloco de código informado.

Vejamos um exemplo baseado no nosso exercício anterior.

[1,2,3,4,5].map do |i|
i*2
end
#=> [2,4,6,8,10]

Observe que não foi preciso um Array “auxiliar” para que tivéssemos o resultado desejado. Ou seja, o .map se encarregou que criar um Array e devolvê-lo com os resultados baseados no bloco (i*2) que passamos, onde o (i) representa cada um dos elementos do Array.

Como geralmente usamos um bloco de código pequeno, podemos usar as chaves para deixar o código ainda mais compacto, veja.

[1,2,3,4,5].map { |i| i*2 }

Olha que legal, nosso algoritmo agora ficou todo em uma única linha. 🙂

O .map, como dito anteriormente, pode ser usado com coleções, como por exemplo o resultado de pesquisas do ActiveRecord.

Imaginando que temos um model User, veja o exemplo:

User.all.map { |user| user.name }
#=> [‘Jackson’, ‘João’, ‘José’]

Ou seja, conseguimos andar em todos os usuários, mostrando ao final um Array apenas com os nomes dos mesmos.

O mais legal é que nesse caso podemos ainda usar um operador chamado “ampersand” (‘e’ comercial) para reduzir ainda mais o que digitamos, veja.

User.all.map(&:name)
#=> [‘Jackson’, ‘João’, ‘José’]

O código acima é equivalente ao anterior, e o “&” praticamente substitui o|user| user.”. Simples, não? 🙂 O detalhe fica por conta de que precisamos usar “parenteses” quando usamos o ampersand e isso inviabiliza fazer construções mais elaboradas como essa:

# sem ampersand
User.all.map { |user| [user.name, user.email] }
#=> [['Jackson', '[email protected]'], ['João', '[email protected]], ['José', '[email protected]]]
# com ampersand
User.all.map(&:[name, email])
syntax error, unexpected ']', expecting '='
User.all.map(&:[name, email])
^

Mas para nossa sorte temos o método .pluck! =)

.pluck

O método .pluck vai permitir que selecionemos um ou mais atributos de resultados do ActiveRecord. Veja

User.all.pluck(:name)
#=>[‘Jackson’, ‘João’, ‘José’]
User.all.pluck(:name,:email)
#=> [['Jackson', '[email protected]'], ['João', '[email protected]], ['José', '[email protected]]

Simples, não?

O único detalhe é que esse método é uma implementação do ActiveRecord, ou seja, não é uma implementação da linguagem Ruby, daí só vai funcionar dentro de projetos Rails, blz?

.collect

Aí você pode estar se perguntando, e o .collect? Bem, o collect é só um outro nome para o .map, ou seja, você pode user .map ou .collect que é a mesma coisa.

Esse nome collect, acredito eu, que é apenas para facilitar a leitura do código em algumas situações, por exemplo…

User.all.collect(&:name)
#=> [‘Jackson’, ‘João’, ‘José’]

A leitura do código acima fica algo como “Colete o nome de todos os usuários”, ou seja, melhor que o .map que ficaria “Mapeie o nome de todos os usuários”. Ok?

Enfim, espero que tenham entendido e gostado de mais essa dica!

Como sempre, não esqueçam de nos seguir nas redes sociais e de assinar a nossa newsletter semanal.

Até a próxima! 😉