List limit number of items

Hi,

is there a preferred way to keep a list number of items under a certain limit ?

In my project there is a GenServer module receiving events and stacking them in a list where only the X last one must be kept for analysis.

Currently I have this implementation :
each time an element is pushed in this list, the size of the list is checked and List.delete_at(list, -1) is called in case the limit has been reached.

It’s simple but I’m feeling it could be improved, specially the part where the size of the list is checked at each new event…

A similar question came up recently; here was my suggestion: Term container supporting `push(term)` and `get_last_100()` - #4 by zachallaun

2 Likes

That looks very interesting, thanks !

Is there a way to the last X elements without dropping them from the queue ?

Yep! Remember that all data structures in Elixir (and Erlang) are immutable, so all you have to do is keep a reference to your original queue.

That said, :queue.get/1 will return just the first element (without modifying the queue).

1 Like

@zachallaun provided a nice solution but for future reference - the data structure OP is looking for is called a ring buffer or an eviction queue.

I do’t think the queue fits my need since the data structure I’m looking for should easily enable to read multiple items and it does not make sense to loop over the values of a queue. So I’m going to stick to the list associated with an integer referencing the length of the list in combination with Enum.take, thanks @zachallaun.

@krasenyp thanks for sharing that knowledge, it’s always useful on the long term to learn about data structures

Whatever works for you!

In case it makes any difference, queues can be split and converted to lists:

def pop_many(q, n) do
  {items, q} = :queue.split(n, q)
  {:queue.to_list(items), q}
end
1 Like