« HE:labs
HE:labs

Quick Tip: Usando #each_with_object

Postado por Matheus Bras em 01/12/2014

Em alguns momentos nos deparamos com a necessidade de iterar sobre uma coleção para gerar outra. E quase sempre pra fazer isso acabamos usando uma variável temporária para inicializar o objeto da nova coleção. Porém, podemos usar #each_with_object para não precisarmos de variáveis temporárias no nosso código.

Inicialmente temos:

1 array = []
2 
3 collection.each do |item|
4   # do something with the item
5   array << item
6 end
7 
8 array

Podemos refatorar isso para:

1 collection.each_with_object([]) do |item, array|
2   # do something with the item
3   array << item
4 end

O método #each_with_object irá retornar o array com os itens ao final da iteração na coleção.

Outro exemplo:

 1 hash = {}
 2 
 3 collection.each do |item|
 4   if hash[item]
 5     hash[item] += 1
 6   else
 7     hash[item] = 1
 8   end
 9 end
10 
11 hash

Podemos refatorar para:

1 collection.each_with_object(Hash.new(0)) do |item, hash|
2   hash[item] += 1
3 end

Usando Hash.new(0) nós já temos um hash que tem suas keys inicializadas com 0 automaticamente. Então só nos resta incrementar o valor dentro do loop.

É importanter notar que este método funciona com objetos mutáveis, não funcionando com inteiros, por exemplo. Porém, existe um gotcha quanto a strings.

1 str = ""
2 str += "abc" # retorna um novo objeto mantendo o antigo em seu estado original.
3 str << "abc" # modifica o objeto original

Então, se for usar uma String como o objeto no método #each_with_object, lembre-se que += não irá modificar o objeto, logo o retorno será a própria string.

Compartilhe

Sabia que nosso blog agora está no Medium? Confira Aqui!