Erlang ets 移除/过滤元素
Posted
技术标签:
【中文标题】Erlang ets 移除/过滤元素【英文标题】:Erlang ets remove / filter element 【发布时间】:2016-03-28 20:36:00 【问题描述】:我使用 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]).
我明白了
[f,7,e,5,d,4|ets_tab] %% the ets_tab is NOT expected.
我该如何解决这个问题?
还有其他 API 会做得更好吗?
【问题讨论】:
您在列表中获得原子ets_tab
的原因是您通过使用Tab
作为ets:foldl/3
的第二个参数将它放在那里,这是初始值折叠累加器。您应该使用 []
作为初始值。
其实我想在那里返回一个空的ets表。如果我使用 [],它可能是一个空列表。对吗?
如果要清空整个表,使用ets:delete_all_objects/1
即可。
@SteveVinoski。谢谢。这是有道理的。
【参考方案1】:
您可能会发现定期删除大量对象可能会导致 在不希望的延迟尖峰。 有一个有趣的项目将缓存段作为单独的 ets 表 并通过删除整个 ets 来删除过时的对象,也许你会发现它也很有趣
https://github.com/fogfish/cache
【讨论】:
感谢分享。但是有了这个缓存,我怎样才能扩展缓存对象的 TTL?【参考方案2】:您不能将 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]
或者您可以使用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]
【讨论】:
在这种情况下编写select_delete
调用的更简单方法是使用ets:fun2ms/1
: ets:select_delete(Tab, ets:fun2ms(fun(_,V) -> V < 3 end)).
谢谢。将使用 ets:select_delete/2
如果您将使用 fun2ms,请不要忘记添加“-include_lib("stdlib/include/ms_transform.hrl")。”在你的 erl 文件中。
顺便说一句,您的第二个示例不起作用。您应该删除对象而不是先插入它们或删除整个表。
是的,我真的忘记了“delete_all_objects”步骤。更新。谢谢!【参考方案3】:
另一种方法是使用 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]
【讨论】:
谢谢。这需要在过滤器之后重新插入。 抱歉,我没有意识到您希望保留两个列表,在这种情况下,您可以分配 Tab1 = [X,Y || X,Y 3]。这样你就可以同时使用 Tab 和 Tab1。以上是关于Erlang ets 移除/过滤元素的主要内容,如果未能解决你的问题,请参考以下文章