Skip to content

Instantly share code, notes, and snippets.

@rugyoga
Created July 19, 2022 22:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rugyoga/d7e3143ca9f8fa206437c127f5d6fc2b to your computer and use it in GitHub Desktop.
Save rugyoga/d7e3143ca9f8fa206437c127f5d6fc2b to your computer and use it in GitHub Desktop.
Chunk a stream based on orderedness, sizer and joiner.
@spec chunker(Enumerable.t(), non_neg_integer(), boolean(), (any() -> non_neg_integer()), (Enumerable.t() -> any())) :: Enumerable.t()
def chunker(
chunks,
chunk_size,
ordered \\ true,
sizer \\ &String.length/1,
joiner \\ &Enum.join/1
) do
zero = {0, []}
convert =
if ordered do
fn chunks -> chunks |> Enum.reverse() |> then(joiner) end
else
joiner
end
final = fn {_, chunks} -> {:cont, convert.(chunks), zero} end
add_chunk = fn {size, chunks}, chunk -> {size + sizer.(chunk), [chunk | chunks]} end
step = fn chunk, accum = {size, chunks} ->
if size >= chunk_size do
{:cont, convert.(chunks), add_chunk.(zero, chunk)}
else
{:cont, add_chunk.(accum, chunk)}
end
end
Stream.chunk_while(chunks, zero, step, final)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment