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.

Reply via email to