If the order of IDs in you list doesnāt matter, you can keep the list sorted to get better performance when inserting or removing IDs.
defmodule IDList do
def new do
[]
end
def add(list, [id | ids]) do
add(add(list, id), ids)
end
def add(list, []) do
list
end
def add(list, id) do
insert_unique(list, id)
end
def rm(list, [id | ids]) do
rm(rm(list, id), ids)
end
def rm(list, []) do
list
end
def rm(list, id) do
remove_unique(list, id)
end
def insert_unique([], id) do
[id]
end
def insert_unique([top | rest], id) when id > top do
[top | insert_unique(rest, id)]
end
def insert_unique([id | rest], id) do
[id | rest]
end
def insert_unique([top | rest], id) do
[id, top | rest]
end
def remove_unique([], _) do
[]
end
def remove_unique([top | rest], id) when top < id do
[top | remove_unique(rest, id)]
end
def remove_unique([id | rest], id) do
rest
end
def remove_unique(rest, _) do
rest
end
end
ExUnit.start()
defmodule IDListTest do
use ExUnit.Case
test "inserting" do
list = IDList.add(IDList.new(), [1, 1, 2, 1, 2, 2, 1])
assert [1, 2] = list
assert list == IDList.add(list, [])
assert [1, 2, 3] = IDList.add(list, 3)
assert [1, 2, 3] = IDList.add(list, [3])
end
test "removing" do
list = IDList.add(IDList.new(), [4, 3, 2, 1])
assert list == IDList.rm(list, [])
assert [1, 2, 3] = IDList.rm(list, 4)
assert [1, 2, 3] = IDList.rm(list, [4])
assert [1, 2, 3] = IDList.rm(list, [4, 4])
assert [2, 3] = IDList.rm(list, [1, 4])
assert [2, 3] = IDList.rm(list, [4, 1])
end
end
Or using a MapSet
could be better too. But in any case 1000 ids āa few times per secondā is small and you should not notice a GC pause for that.