1

ETS テーブル内のすべてのタプルに関数を適用したいと思います。

テーブルはセットで、各キーは 1 回だけ表示されます。

私のテーブルには、同じタイプのタプルのみが含まれています。

{Key, X, Y, VX, VY}

すべての値は::integer()

私がしたいのは、特定の値を経過させ、すべてのタプルを関数で更新することです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_elementXとYを更新するためにVXとVYの値を読む必要があるので使えません。

  • いくつかの反復子ユーティリティがあることは知っていますが、楽しみを渡すことを誰も許可していないようです。

この更新は 1 ~ 5 秒ごとに行う必要があります。では、10個のタプルで最も効率的なソリューションはどれですか? 100個のタプルで?もっと?

ありがとう !

ボートのリストを保持します。キーはボート ID、X と Y は地理座標、VX と VY は動きのベクトル (1 秒間の変位) を表します。Elapsed は比率であり、最後の更新からの秒数です。テーブルは、各ボートの位置をいつでも知るのに役立ちます。

4

2 に答える 2

1

私はおそらくこれにets:foldlを使用します。

このデータへの反復アクセスのみが必要であるように私には思えます。したがって、ここでレコードのリストを使用できます。

もう1つのアプローチ(私が求める)は、ボートスーパーバイザーを配置し、すべてのボートに対してgen_serverを作成することです。そうすれば、すべてのボートに独自の状態があり、実際にリストをトラバースする必要はありません。

また、qlc http://www.erlang.org/doc/man/qlc.html qlcをチェックアウトして、etsまたはmnesiaテーブルでリスト内包表記を使用しましょう。ただし、foldlと同じパフォーマンスになる可能性があります。

于 2013-02-20T09:03:47.207 に答える
1

あなたがしていることを行うための素晴らしい方法はありません。

最近、私は同様の問題に遭遇しました(1秒に1回、約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 秒ごとにテーブルを更新する必要もありません。基本的に、ボートが報告するたびにテーブルを更新するだけです。

于 2013-02-20T09:17:04.133 に答える