In my current project, I have an existing list of unique objects (A0), and
an updated representation of that list (A1).
I need to group A1 into thee lists: {added, still_present, removed} by
comparing it to the state of A0 (then take an action on the added and
removed items, but thats unrelated to this proposal).
Since each item is unique, once I determine that an item is "still_present"
that item no longer needs to be part of the list which we use in
determining grouping for the next item.
I coming up with the solution for that task, I came up with Enum.pop_by/2,
with the following implementation.
@doc """
Returns a tuple with the popped value and the remainder of the list. The
popped value is found
by the given function. Once it finds the popped value, it stops searching
and returns the result.
Example:
pop_by([1, 2, 3], fn a -> a == 2 end)
> {2, [1, 3]}
# No item returns nil and unchanged list
pop_by([1, 2, 3], fn a -> a == 4 end)
> {nil, [1, 2, 3]}
"""
def pop_by(enumerable, fun), do: do_pop_by(enumerable, fun)
defp do_pop_by(enumerable, fun, collector \\ [])
defp do_pop_by([], _fun, collector), do: {nil, Enum.reverse(collector)}
defp do_pop_by([head | tail], fun, collector) do
if fun.(head) do
# found item! Reverse collector to maintain original list order and concat
to tail
{head, Enum.reverse(collector) ++ tail}
else
do_pop_by(tail, fun, [head | collector])
end
end
What do you think? Could also make the collector reversal optional which
would improve time complexity in cases where the order of list doesn't need
to be maintained
--
You received this message because you are subscribed to the Google Groups
"elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/elixir-lang-core/95fe802e-5852-4fd3-9d4e-9382b80afe7d%40googlegroups.com.