0

StackOverflow でこの質問に対する答えが見つからないことに驚いています (検索が正しくない可能性があります)。

しかし、基本的には Array.indexOf() メソッドに似たものがあるかどうか知りたいのですが、オブジェクト用です。つまり、既存のオブジェクト内の値のインデックスを返す効率的な方法です。

たとえば、次のオブジェクトがあるとします。

var obj = { prop1: "a", prop2: "b", prop3: "c", prop4: "a" };

ここで、「a」を含むインデックスを見つけたいと思います。a を実行して、次のobj.indexOf("a")ような値を返すとよいでしょう。["prop1", "prop4"]

しかし、これはオブジェクト用に実装されたメソッドではないようです。

または、関数を作成できることを知っています。

function indexOf(val, obj){
  var indexes = [];

  for (var index in obj){
      if(!obj.hasOwnProperty(index)) continue;

      if(obj[index] == val){
        indexes.push(index);
      }   
   }

   if(!indexes.length) return false;
   else return indexes;
}

indexOf("a", obj); // returns ["prop1","prop4"]

しかし、このような方法でオブジェクト全体を反復処理するのは面倒です!! これから扱うオブジェクトの中には非常に大きく、値も非常に大きくなるものがあります。

より良い、より効率的な方法はありますか?

4

1 に答える 1

1

非常に巨大なオブジェクトがある場合は、O(1) の複雑さを持つ優れたweakmap実装 を使用して、単一のオブジェクトごとにキーを格納できます。そのため、ハッシュ コレクションを実装する必要があるため、キーと値のペアを設定するときに、キーもweakmapに保存します。ベンチも作りました。このカスタム HashMap と RawObject 検索の比較 - jsperf

function HashMap() {
    this.__map = new WeakMap;
    this.__hash = {};
}

HashMap.prototype = {
    set: function(key, value){
        this.unset(key);

        if (value == null) 
            return;

        this.__hash[key] = value;

        var keys = this.__map.get(value);
        if (keys == null) 
            this.__map.set(value, keys = []);

        keys.push(key);
    },
    unset: function(key){
        var value = this.__hash[key];
        if (value) {

            var keys = this.__map.get(value),
                index = keys.indexOf(key);

            keys.splice(index, 1);
        }
        this.__hash[key] = void 0;
    },

    get: function(key){
        return this.__hash[key];
    },
    getKeys: function(value){
        return this.__map.get(value);
    }
};

WeakMap はObject.definePropertyコアでメソッドを使用します。このため、いくつかの制限があります。

  • ブラウザ: IE9+
  • 上記の HashMap の例の値としてのオブジェクトは、WeakMap コレクションでキーとして使用されるためです。

しかし、このアプローチは、特定の値を探すためにオブジェクトを反復処理する必要がないため、パフォーマンスを大幅に向上させます。

于 2013-11-09T00:35:13.870 に答える