Packages

Convert a list of nested maps to `list(list(String.t))` or CSV. Can be used with GraphQL or Ecto.

Current section

Files

Jump to
list_to_csv lib list_to_csv option.ex
Raw

lib/list_to_csv/option.ex

defmodule ListToCsv.Option do
@moduledoc """
`ListToCsv.Option` contains types and utilities for option.
"""
alias ListToCsv.Header
alias ListToCsv.Key
@type t() :: [
headers: list(Header.t()) | nil,
keys: list(Key.many()),
length: list({Key.many(), integer}) | nil
]
@spec expand(t()) :: list({Header.t(), Key.many()} | Key.many())
def expand(option) do
headers = option[:headers]
keys = option[:keys]
length = option[:length]
case {headers, length} do
{nil, nil} ->
keys
{headers, nil} ->
Enum.zip(headers, keys)
{nil, length} ->
Enum.reduce(length, keys, &do_expand/2)
_ ->
Enum.reduce(length, Enum.zip(headers, keys), &do_expand/2)
end
end
@spec do_expand({Key.many(), integer()}, list({Header.t(), Key.many()} | Key.many())) ::
list({Header.t(), Key.many()} | Key.many())
def do_expand({keys, n}, headers) do
matcher = &starts_with?(&1, Key.build_prefix(keys))
case chunks(headers, matcher) do
{prefix, body, []} ->
Enum.concat(prefix, duplicate(body, n))
{prefix, body, suffix} ->
Enum.concat([prefix, duplicate(body, n), do_expand({keys, n}, suffix)])
end
end
def duplicate([{_, _} | _] = list, n) do
{headers, keys} = Enum.unzip(list)
Enum.zip(Header.duplicate(headers, n), Key.duplicate(keys, n))
end
def duplicate(list, n), do: Key.duplicate(list, n)
def starts_with?({_, keys}, prefix), do: Key.starts_with?(keys, prefix)
def starts_with?(keys, prefix), do: Key.starts_with?(keys, prefix)
@doc """
split list 3 part with respect orders
- 1st not matched with `fun`
- 2nd matched with `fun`
- 3rd not matched with `fun`
## Examples
iex> chunks([1, 2, 3, 2, 1, 3, 2], &(&1 == 3))
{[1, 2], [3], [2, 1, 3, 2]}
"""
@spec chunks(list(), function()) :: {list(), list(), list()}
def chunks(list, fun) do
{prefix, tail} = Enum.split_while(list, &(!fun.(&1)))
{body, suffix} = Enum.split_while(tail, fun)
{prefix, body, suffix}
end
end