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) -&gt; V &lt; 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 移除/过滤元素的主要内容,如果未能解决你的问题,请参考以下文章

Erlang ets:选择子列表

Erlang ETS Table

Erlang - ETS 表之间的比较

在不使用保护子句的情况下过滤 erlang ets 表

erlang ets 选择错误的参数

Erlang应该如何过滤列表中的元素,并添加标点和[]?