Skip to content

Instantly share code, notes, and snippets.

@mareksuscak
Last active September 1, 2017 21:54
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 mareksuscak/acb4de6f72b2e6983c7c22b64bf7ce8a to your computer and use it in GitHub Desktop.
Save mareksuscak/acb4de6f72b2e6983c7c22b64bf7ce8a to your computer and use it in GitHub Desktop.
Idiomatic deep flatten implementation in Elixir.
defmodule Array do
def flatten(list), do: flatten(list, [])
def flatten([head | tail], acc) when head == [], do: flatten(tail, acc)
def flatten([head | tail], acc) when is_list(head), do: flatten(tail, flatten(head, acc))
def flatten([head | tail], acc), do: flatten(tail, acc ++ [head])
def flatten([], acc), do: acc
end
@veelenga
Copy link

veelenga commented Sep 1, 2017

Copied from here.

@mareksuscak ++ is very expensive operation. Check out this benchmark:

defmodule FlattenReverse do
  def flatten(list), do: flatten(list, []) |> Enum.reverse
  def flatten([h | t], acc) when h == [], do: flatten(t, acc)
  def flatten([h | t], acc) when is_list(h), do: flatten(t, flatten(h, acc))
  def flatten([h | t], acc), do: flatten(t, [h | acc])
  def flatten([], acc), do: acc
end

defmodule FlattenAppend do
  def flatten(list), do: flatten(list, [])
  def flatten([h | t], acc) when h == [], do: flatten(t, acc)
  def flatten([h | t], acc) when is_list(h), do: flatten(t, flatten(h, acc))
  def flatten([h | t], acc), do: flatten(t, acc ++ [h])
  def flatten([], acc), do: acc
end

list = List.duplicate(0, 200) |> List.duplicate(200)

{time, _} = :timer.tc fn -> FlattenReverse.flatten(list) end
IO.puts "Flatten reverse took #{time}"

{time, _} = :timer.tc fn -> FlattenAppend.flatten(list) end
IO.puts "Flatten append took #{time}"
Flatten reverse took 2637
Flatten append took 3240488

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment