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.