我想将一个函数应用于ETS表中的所有元组:
表是一个集合,每个键只出现一次。
我的表只包含相同类型的元组:
{Key, X, Y, VX, VY}
所有值均为::integer()
我想做的是有一个特定的值Elapsed并更新所有具有函数apply_vector/2
的我的元组
apply_vector({K, X, Y, 0, 0}, _Elapsed) ->
{K, X, Y, 0, 0};
apply_vector({K, X, Y, VX, VY}, Elapsed) ->
NewX = X + (VX * Elapsed),
NewY = Y + (VY * Elapsed),
{K, NewX, NewY, VX, VY}.
可能的解决方案
如果我使用
ets:foldl
,我的插入可以在折叠过程中被遍历,并且导致一个无限(非常长)的循环。我可以用
ets:foldl
准备新的元组,然后插入整个列表我可以插入一个新表,然后用新表替换旧表,但我不想通过调用gen_server,表必须在任何时候都可以访问。
我不能使用
ets:update_element
,因为我需要读取VX和VY值以更新X和Y。我知道有一些迭代器实用程序,但似乎没有人允许传递乐趣。
我需要每1-5秒更新一次。因此,维奇的解决方案是有10个元组的效率最高?有100个元组?还有更多?
谢谢!
我保存一份船只列表,关键是船只ID,X和Y是地理位置坐标,VX和VY表示运动矢量:位移一秒钟。Elapsed是一个比率,是自上次以来的秒数使现代化这张表有助于随时了解每艘船的位置。
我可能会使用ets:foldl。
在我看来,你只需要对这些数据进行迭代访问。所以你可以在这里使用记录列表。
另一种方法(我会选择)是设置一个船只管理器,并为每艘船创建一个gen_server。这样,每艘船都会有自己的状态,你实际上不需要遍历任何列表。
同时签出qlchttp://www.erlang.org/doc/man/qlc.htmlqlc让您在ets或mnesia表上使用列表理解。不过,它可能会有与foldl相同的性能。
没有什么好方法可以做你正在做的事情。
最近,我遇到了一个类似的问题(每秒更新约5000行)
这让我采取了一种完全不同的方法
那么,您需要存储解释的值吗?或者您可以在查找时计算值吗?
如何存储:{K、X、Y、VX、VY、LastUpdateTime}
然后做一些类似(不可编译的例子):
boats:get_all() -> % Record syntax would be smarter here, but it's an example...
ets:foldl(?TABLE,[],fun(Row={Id,_,_,_,_,_},Acc) -> [{Id,calc(Row)}|Acc] end).
boats:get(Id) ->
[Row] = ets:lookup(?TABLE,Id),
calc(Row).
calc({_K,X,Y,VX,VY,LastUpdate}) ->
{X + (VX * (now() - LastUpdate)), Y + (VY * (now() - LastUpdate)}
这使您不必在genserver上进行阻塞,也不必每5秒更新一次表。你基本上只会在每次船只报告时更新表格。