Ruby: métodos chunk e chunk_while

Dicas - 28/Mar/2021 - por André Kanamura

Em desenvolvimento de software uma ação que executamos com frequência é agrupar dados de um array de acordo com algum critério específico como, por exemplo, separar números pares dos demais. Em Ruby, uma maneira fácil de fazer isso é usando o método group_by:

[1, 3, 2, 4, 6, 2, 3, 4, 6].group_by{ |elem| elem.even? }

 => {false=>[1, 3, 3], true=>[2, 4, 6, 2, 4, 6]} 

O método retorna em uma hash com os valores separados de acordo com o critério utilizado dentro do bloco, neste caso .even? (que avalia se um número é par), e isso resultou em dois grupos, um com os números pares e outro com os ímpares.

E se quisermos agrupar os valores consecutivos desse array? No exemplo acima, por exemplo, 2, 4 e 6 são pares consecutivos. Para essa situação, o Ruby possui outro método que faz exatamente o que precisamos, o chunk:

[1, 3, 2, 4, 6, 2, 3, 4, 6].chunk { |elem| elem.even? }.each { |e| p e }

[false, [1, 3]]
[true, [2, 4, 6, 2]]
[false, [3]]
[true, [4, 6]]

 => nil 

Como o retorno desse método é um Enumerator, precisamos usar o each e usar o método p para imprimir o resultado em tela e visualizarmos o resultado. Da mesma maneira que no group_by, devemos passar ao método chunk um bloco de código que define o critério para o agrupamento de valores. Note como, além de termos separados os valores pares dos ímpares, podemos ver claramente aqueles que são consecutivos. O retorno do método entrega os dados organizadinhos em arrays junto com o boolean resultado do critério passado ao método. :)

Mas o Ruby ainda possui outro método ainda mais poderoso, o chunk_while. Ele faz algo semelhante ao chunk, agrupando elementos consecutivos de acordo com um critério. A diferença é que o chunk_while expõe em variáveis os elementos que estão sendo avaliados, permitindo implementar critérios que envolvem a relação entre esses dois elementos. Isso vai ficar mais claro com um exemplo. Considere o mesmo conjunto de dados anteriores, mas dessa vez vamos agrupar os valores consecutivos que estão em ordem crescente, ou seja, um elemento é sempre menor que o elemento seguinte.

[1, 3, 2, 4, 6, 2, 3, 4, 6].chunk_while { |a, b| a < b }.each { |e| p e }

[1, 3]
[2, 4, 6]
[2, 3, 4, 6]

 => nil

Esse método é muito interessante e permite aplicar diferentes regras de relação entre valores consecutivos e deixar o código de nossas aplicações muito mais enxuto.

Referências e outras leituras

Foto de perfil do autor
André Kanamura

Dev na Campus Code