Search code examples
crystal-lang

Is there a way to group_by with_index in Crystal?


So I have this (nicely sorted) array.

And sometimes I need all of the elements from the array. But other times I need all of the even-indexed members together and all of the odd-indexed members together. And then again, sometimes I need it split into three groups with indices 0,3,6 etc. in one group, then 1,4,7 in the next and finally 2,5,8 in the last.

This can be done with group_by and taking the modulus of the index. See for yourself:

https://play.crystal-lang.org/#/r/4kzj

arr = ['a', 'b', 'c', 'd', 'e']
puts arr.group_by { |x| arr.index(x).not_nil! % 1 } # {0 => ['a', 'b', 'c', 'd', 'e']}
puts arr.group_by { |x| arr.index(x).not_nil! % 2 } # {0 => ['a', 'c', 'e'], 1 => ['b', 'd']}
puts arr.group_by { |x| arr.index(x).not_nil! % 3 } # {0 => ['a', 'd'], 1 => ['b', 'e'], 2 => ['c']}

But that not_nil! in there feels like a code-smell / warning that there's a better way.

Can I get the index of the elements without needing to look it up and handle the Nil type?


Solution

  • You can also just do:

    arr = ['a', 'b', 'c', 'd', 'e']
    i = 0
    puts arr.group_by { |x| i += 1; i % 1 }
    i = 0
    puts arr.group_by { |x| i += 1; i % 2 }
    i = 0
    puts arr.group_by { |x| i += 1; i % 3 }