Erlang ets 删除/过滤元素
Erlang ets remove / filter element
我使用 elang ets table 作为一个简单的缓存。我想使用一个进程来扫描 table 并删除过期的元素(多个)。
和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]).
我得到了
[{f,7},{e,5},{d,4}|ets_tab] %% the ets_tab is NOT expected.
我该如何解决这个问题?
还有其他 API 会做得更好吗?
您不能将 ets table 用作累加器。
为了您的目的,您可以使用 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, [{{'',''},[{'=<','',3}],[true]}]).
3
4> ets:tab2list(Tab).
[{f,7},{e,5},{d,4}]
或者您可以使用 ets:tab2list/1 获取所有值的列表,过滤它们,然后重新插入到 table:
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}]
另一种方法是使用 list comprehensions.
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> [{X,Y} || {X,Y} <- ets:tab2list(Tab), Y>3].
[{f,7},{e,5},{d,4}]
您可能会发现,定期删除大量对象可能会导致
在不受欢迎的延迟尖峰。
有一个有趣的项目将缓存段作为单独的 ets 表
并通过删除整个 ets 来删除过时的对象,也许你会发现它也很有趣
我使用 elang ets table 作为一个简单的缓存。我想使用一个进程来扫描 table 并删除过期的元素(多个)。
和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]).
我得到了
[{f,7},{e,5},{d,4}|ets_tab] %% the ets_tab is NOT expected.
我该如何解决这个问题?
还有其他 API 会做得更好吗?
您不能将 ets table 用作累加器。
为了您的目的,您可以使用 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, [{{'',''},[{'=<','',3}],[true]}]).
3
4> ets:tab2list(Tab).
[{f,7},{e,5},{d,4}]
或者您可以使用 ets:tab2list/1 获取所有值的列表,过滤它们,然后重新插入到 table:
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}]
另一种方法是使用 list comprehensions.
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> [{X,Y} || {X,Y} <- ets:tab2list(Tab), Y>3].
[{f,7},{e,5},{d,4}]
您可能会发现,定期删除大量对象可能会导致 在不受欢迎的延迟尖峰。 有一个有趣的项目将缓存段作为单独的 ets 表 并通过删除整个 ets 来删除过时的对象,也许你会发现它也很有趣