如何设置队列来保存N个值。到达N时,删除最后一项并将值添加到队列的前面。
这应该用if语句完成吗?
我还想在添加新项目时计算队列中的值。例如添加队列中的所有值。
答案 0 :(得分:6)
我从你的查询中假设你们都希望最大化队列的长度并获得所有值的总和。
首先回答你最简单的问题:Erlang队列,无论你想表示它们,都是正常的Erlang数据结构,所以将它们存储在字典中没有问题。
OTP queue
模块实际上非常简单,但过多的界面很容易让人感到困惑。通过不直接使用queue
数据结构,但通过定义自己的数据结构(包括队列及其当前长度{Length,Queue}
),可以提高@Nathon的入队函数的效率。如果总和很重要,那么你甚至可以包括它。
队列表示非常简单,因此很容易编写自己的专用形式。
最简单的方法是将队列保留在列表中并从头部获取元素并将新元素添加到结尾。所以:
new(Max) when is_integer(Max), Max > 0 -> {0,Max,[]}. %Length, Max and Queue list
take({L,M,[H|T]}) -> {H,{L-1,M,T}}.
add(E, {L,M,Q}) when L < M ->
{L+1,M,Q ++ [E]}; %Add element to end of list
add(E, {M,M,[H|T]}) -
{M,M,T ++ [E]}. %Add element to end of list
当队列变满时,将丢弃位于队列前面的最旧成员。空队列会生成错误。这是一个非常简单的结构,但由于每次添加新元素时都会复制队列,因此效率很低。反转列表没有用,因为每次从中删除元素时都会复制列表。但这很简单,而且确实有效。
更有效的结构是将队列拆分为两个列表,即队列的前端和队列的后端。后端相反,当前部空了时成为新的前部。所以:
new(Max) when is_integer(Max), Max > 0 ->
{0,Max,[],[]}. %Length, Max, Rear and Front
take({L,M,R,[H|T]}) -> {H,{L-1,M,R,T}};
take{{L,M,R,[]}) when L > 0 ->
take({L,M,[],lists:reverse(R)}). %Move the rear to the front
add(E, {L,M,R,F}) when L < M ->
{L+1,M,[R|E],F}; %Add element to rear
add(E, {M,M,R,[H|T]}) ->
{M,M,[R|E],T}; %Add element to rear
add(E, {M,M,R,[]}) ->
add(E, {M,M,[],lists:reverse(R)}). %Move the rear to the front
当队列变满时,队列前面的最旧成员将被删除,空队列会生成错误。这是queue
模块中使用的数据结构。
将元素的当前总和添加到结构并直接管理它将非常容易。
通常,在处理这样的简单数据结构时,滚动自己的模块就像使用提供的模块一样容易。
答案 1 :(得分:4)
鉴于这些评论,我们会这样做:
enqueue(Value, Queue) ->
Pushed = queue:in(Value, Queue),
Sum = fun (Q) -> lists:sum(queue:to_list(Q)) end,
case queue:len(Pushed) of
Len when Len > 10 ->
Popped = queue:drop(Pushed),
{Popped, Sum(Popped)};
_ ->
{Pushed, Sum(Pushed)}
end.
如果您实际上并不想对项目求和,则可以使用lists:foldl
代替,或者只编写一个函数直接在队列上执行操作。