Erlang ets删除/过滤元素

use*_*708 4 erlang fold ets

我使用elang ets表作为简单的缓存.我想使用进程扫描表并删除过期的元素(多个).

与ets:foldl

expire_table_example() ->
Tab = ets:new(ets_tab, [named_table, set]),
ets:insert(Tab, [{a, 1}, {b, 2}, {c, 3}, {d, 4}, {e, 5},{f,7}]),
Tab1 = ets:foldl(fun({Key, Val}, Acc) ->
if
   (Val > 3) -> [{Key, Val} | Acc];
   true -> Acc
 end
end, Tab, Tab),
io:format("end ~p ~n", [Tab1]).
Run Code Online (Sandbox Code Playgroud)

我有

[{f,7},{e,5},{d,4}|ets_tab] %% the ets_tab is NOT expected.
Run Code Online (Sandbox Code Playgroud)

我怎样才能解决这个问题?

任何其他API会做得更好吗?

P_A*_*P_A 5

您不能将ets表用作累加器.

为了您的目的,您可以使用ets:select_delete/2:

1> Tab = ets:new(ets_tab, [named_table, set]).
ets_tab
2> ets:insert(Tab, [{a, 1}, {b, 2}, {c, 3}, {d, 4}, {e, 5},{f,7}]).
true
3> ets:select_delete(Tab, [{{'$1','$2'},[{'=<','$2',3}],[true]}]).
3
4> ets:tab2list(Tab).
[{f,7},{e,5},{d,4}]
Run Code Online (Sandbox Code Playgroud)

或者您可以使用ets:tab2list/1获取所有值的列表,过滤它们,然后重新插入到表中:

1> Tab = ets:new(ets_tab, [named_table, set]).
ets_tab
2> ets:insert(Tab, [{a, 1}, {b, 2}, {c, 3}, {d, 4}, {e, 5},{f,7}]).
true
3> L = ets:tab2list(Tab).
[{f,7},{e,5},{d,4},{c,3},{b,2},{a,1}]
4> L2 = lists:filter(fun({Key,Val}) -> Val > 3 end, L).
[{f,7},{e,5},{d,4}]
5> ets:delete_all_objects(Tab).
true
6> ets:insert(Tab, L2).
true
7> ets:tab2list(Tab).
[{f,7},{e,5},{d,4}]
Run Code Online (Sandbox Code Playgroud)

  • 为这种情况编写`select_delete`调用的一种更简单的方法是使用[`ets:fun2ms/1`](http://www.erlang.org/doc/man/ets.html#fun2ms-1): ets:select_delete(Tab,ets:fun2ms(fun({_,V}) - > V <3 end)). (4认同)