Skip to content

Instantly share code, notes, and snippets.

@pragdave
Created July 15, 2013 01:57
Show Gist options
  • Save pragdave/5997018 to your computer and use it in GitHub Desktop.
Save pragdave/5997018 to your computer and use it in GitHub Desktop.
Two implementations of flatten/1
# The simplest version is probably to use list concatenation. However,
# this version ends up rebuilding the list at each step
defmodule UsingConcat do
def flatten([]), do: []
def flatten([ head | tail ]), do: flatten(head) ++ flatten(tail)
def flatten(head), do: [ head ]
end
# This version is more efficient, as it picks successive head values
# from a list, adding them to `result`. The trick is that we have to
# unnest the head if the head itself is a list.
defmodule MyList do
def flatten(list), do: _flatten(list, [])
defp _flatten([], result), do: Enum.reverse(result)
# The following two function heads deal with the head
# being a list
defp _flatten([ [ h | [] ] | tail], result) do
_flatten([ h | tail], result)
end
defp _flatten([ [ h | t ] | tail], result) do
_flatten([ h, t | tail], result)
end
# Otherwise the head is not, and we can collect it
defp _flatten([ head | tail ], result) do
_flatten(tail, [ head | result ])
end
end
IO.inspect MyList.flatten([ 1, [ 2, 3, [4] ], 5, [[[6]]]])
@josevalim
Copy link

Here is another way to implement flatten (not tail recursive but it probably doesn't matter):

defmodule MyFlatten do
  def flatten(list), do: do_flatten(list, [])

  def do_flatten([h|t], tail) when is_list(h) do
    do_flatten(h, do_flatten(t, tail))
  end

  def do_flatten([h|t], tail) do
    [h|do_flatten(t, tail)]
  end

  def do_flatten([], tail) do
    tail
  end
end

IO.inspect MyFlatten.flatten([ 1, [ 2, 3, [4] ], 5, [[[6]]]])

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