0

i have a data structure of a flat array of numbers

[145, 46, 200, 3, 178, 206, 73, 228, 165, 65, 6, 141, 73, 90, 181, 100]

i need to make an array of arrays with a max of 3 items per sub array. So i look at some examples, and Enum.chunk(arr, n) seems like a candidate

so .chuck(arr, 3) says its deprecated, use chuck_every(arr, 3) instead, so i did that and it produces a strange result vs chunk

for example: chunk returns

[[145, 46, 200], [3, 178, 206], [73, 228, 165], [65, 6, 141], [73, 90, 181]]

while chunk_every returns

[145, 46, 200],
[3, 178, 206],
[73, 228, 165],
[65, 6, 141],
[73, 90, 181],
'p']

the main difference being an extra random element which is a string???

it's almost like it converted the element that chunk cuts off and converts it to a string?

Naturally I am expecting the replacement method would have the same output given the same input. Right?

Adam Millerchip
  • 20,844
  • 5
  • 51
  • 74
Denis S Dujota
  • 543
  • 5
  • 13
  • _Sidenote:_ `'d'` is not “a string” by any mean, it’s _a charlist_ effectively equal to `[100]`: `[100] == 'd' #⇒ true`. – Aleksei Matiushkin Mar 28 '21 at 16:03
  • 2
    _Sidenote:_ [tag:elixir] does not have arrays (unless you use `:array` module from [tag:erlang].) There are lists only. – Aleksei Matiushkin Mar 28 '21 at 16:14
  • It's a good job you asked about `chunk` vs `chunk_every`, otherwise this would have been closed as a duplicate of [Elixir lists interpreted as char lists](https://stackoverflow.com/questions/30037914/elixir-lists-interpreted-as-char-lists). – Adam Millerchip Mar 29 '21 at 06:23

3 Answers3

4

Look at last element: 100. chunk seems to discard that value while chunk_every add it at last element alone. That is the p character you see. Elixir try to show as chars arrays of numbers in the console, as that is its internal representation.

As you can see in the documentation, you can pass :discard as leftover parameter to behave as deprecated chunk function.

https://hexdocs.pm/elixir/Enum.html#chunk_every/2

Mou
  • 2,027
  • 1
  • 18
  • 29
  • 2
    so based on the docs i adjusted to `Enum.chunk_every(arr, 3, 3, :discard)`. to get the same result as just `chunk(arr, 3)` seems a bit odd but i guess this is saying chunk the array into 3 elements every 3 elements and discard the remainder? – Denis S Dujota Mar 28 '21 at 15:45
  • That's it. It's kind a generic more powerful function – Mou Mar 28 '21 at 15:54
  • i have to admit, at first i was a bit resistant to the new signature, but you're right it nice to have a more generic function for chunking – Denis S Dujota Mar 28 '21 at 16:43
  • Please, add examples on the main reply, as @DenisSDujota did on the comment. – JuliSmz Jun 16 '22 at 18:48
1

Enum.chunk_every/4 was designed by this, actually its a number if you do like this:

[145, 46, 200, 3, 178, 206, 73, 228, 165, 65, 6, 141, 73, 90, 181, 100]
|> Enum.chunk_every(3, 3, [])
|> Enum.each(fn item ->
  IO.inspect item, charlists: false
end)

you can find more detail from official discussion:

https://github.com/elixir-lang/elixir/issues/7260

hulin
  • 151
  • 3
  • This doesn't really answer the question regarding the difference between `chunk`, and `chunk_every`. It just points out the charlists behaviour, which is already answered on [Elixir lists interpreted as char lists](https://stackoverflow.com/questions/30037914/elixir-lists-interpreted-as-char-lists). – Adam Millerchip Mar 30 '21 at 03:38
0

Sometimes it makes sense to implement basic functionality ourselves, instead of looking up the standard library, for the precisely controlled result.

Here is a recursive implementation, that discards the tail.

input =
  [145, 46, 200, 3, 178, 206, 73, 228,
   165, 65, 6, 141, 73, 90, 181, 100]

defmodule MyEnum do
  def chunk_3(input), do: do_chunk_3(input, [])
  defp do_chunk_3([e1, e2, e3 | rest], acc),
    do: do_chunk_3(rest, [[e1, e2, e3] | acc])
  defp do_chunk_3(_, acc), do: Enum.reverse(acc)
end

MyEnum.chunk_3(input)
#⇒ [[145, 46, 200],
#   [3, 178, 206],
#   [73, 228, 165],
#   [65, 6, 141],
#   [73, 90, 181]]
Aleksei Matiushkin
  • 119,336
  • 10
  • 100
  • 160