7

javascriptに単純な不変のハッシュと配列の実装はありますか?最高の速度は必要ありません。クローンよりも妥当な速度が良いでしょう。

また、Javaやその他の言語で簡単に理解してJavaScriptに移植できる簡単実装があれば、それもいいでしょう。

アップデート:

目標は、ハッシュ(または配列)を凍結することだけではなく、更新操作を効率的に実装することです。不変のハッシュを更新すると、新しい不変のハッシュが返されます。そして、「オリジナルのクローンを作成して更新する」よりも効率的であるはずです。

ネイティブJSタイプには、O(1)のような更新の複雑さがあり、クローン作成では複雑さはO(n)になり、特別な不変データ構造(私が求めたもの)では0(log(n))になります。

UPDATE2: JavaScriptにはすでに配列/ハッシュがあります:

はい、しかしそれらは可変です。私は似ているが不変のものが必要です。基本的にはクローン作成によって非常に簡単に実行できますが、非常に非効率的です。hash2 = hash1.clone(); hash2[key] = valueを使用せずに非常に効率的にするアルゴリズムがありますclone

hash1 = {}
hash2 = hash1.set('key', 'value2')
hash3 = hash1.set('key', 'value3)

console.log(hash1) // => {}
console.log(hash2) // => {key: 'value2'}
console.log(hash3) // => {key: 'value3'}

解決:

これは不変のハッシュの実装ではありませんが、私の現在の問題のハックのようなものであり、誰かを助けるかもしれません。

不変のデータ構造が必要な理由についてもう少し詳しく説明します。Node.jsと一種のインメモリデータベースを使用しています。1つのリクエストでデータベースを読み取ることができ、他のリクエストでデータベースを更新する-更新に時間がかかる(リモートサービスを呼び出す)-したがって、すべての読み取りプロセスをブロックして更新が完了するまで待つことができず、更新が失敗する可能性があり、データベースをロールバックする必要があります。そのため、インメモリデータベースへの(ACID)読み取りおよび書き込み操作を何らかの方法で分離する必要があります。

そのため、ある種のMVCCを実装するには、不変の配列とハッシュが必要です。しかし、それを行うためのより簡単な方法があるようです。データベースを直接更新する代わりに、更新操作はデータベースへの変更を記録するだけです(ただし、直接実行することはありません)。「42を配列db.someArrayに追加」の形式で。

結局、更新操作の結果はそのような変更コマンドの配列になり、非常に迅速に適用できるため、データベースをブロックして適用することができます。

ただし、JavaScriptに不変のデータ構造が実装されているかどうかを確認するのは興味深いので、この質問は開いたままにしておきます。

4

4 に答える 4

4

私は JS の永続的なデータ構造に対して同じ要件を持っていたので、少し前に永続的なマップの実装を作成しました.. https://github.com/josef-jelinek/cofy/blob/master/lang/feat.js

これには、バランスの取れたツリー ベース (ソート済み) マップの実装と、単純なコピー オン ライト マップ (および未完成の永続的なベクトル/配列) が含まれています。

var map = FEAT.map();
var map1 = map.assoc('key', 'value');
var value = map1.get('key');
var map2 = map1.dissoc('key');
...

、 、 count()、 、 、 、 、 、 、 、 contains(key)、 、keys(into = [])values(into = [])toObject(into = {})toString()

実装はそれほど複雑ではなく、パブリック ドメインです。私も提案と貢献者を受け入れます:)。

更新: https://github.com/josef-jelinek/cofy/blob/master/tests/test-feat.htmlで単体テスト (使用例) を見つけることができます

更新 2 : 次の操作を含む永続的なベクターの実装が追加されました: count()get(i)set(i, value)push(value)pop()toArray(into = [])toString()

于 2012-11-10T13:15:56.923 に答える
0

オブジェクトを不変にする唯一の方法は、オブジェクトを関数内に隠すことです。その後、関数を使用して既定のハッシュまたは更新されたバージョンのいずれかを返すことができますが、グローバル スコープに不変のハッシュを実際に格納することはできません。

function my_hash(delta) {
    var default = {mykey: myvalue};
    if (delta) {
        for (var key, value in delta) {
            if (default.hasOwnProperty(key)) default[key] = value;
        }
    }
    return default;
}

私はこれが良い考えだとは思いません。

于 2012-11-09T19:16:08.077 に答える
0

私が知っているJavascriptでオブジェクトを複製する最良の方法は、underscore.jsに含まれているものです

まもなく:

_.clone = function(obj) {
  if (!_.isObject(obj)) return obj;
  return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
};

_.extend = function(obj) {
  each(slice.call(arguments, 1), function(source) {
    for (var prop in source) {
      obj[prop] = source[prop];
    }
  });
  return obj;
};
于 2012-11-09T19:21:50.353 に答える