6

ECMA-262で定義されarray.map()ている関数を使用することは非常に簡単に実装できます。この関数は、要素値、インデックス、配列の3つの引数によって呼び出されます。

しかし、スパース配列についてはどうでしょうか?明らかに、インデックス0、1、2、および100,000のみに要素があり、それ以外の場合はインデックス3から99,999までスパースである場合、インデックス0から100,000まで反復する必要はありません。arr.slice(0)配列を使用またはarr.concat()複製してから、置き換えられた値を入力することを考えることができますが、sliceまたはを使用しない場合、それを行うconcat別の方法はありますか?

私が使用することを思いついた解決策slice()は次のとおりです。

Array.prototype.collect = Array.prototype.collect || function(fn) {
    var result = this.slice(0);

    for (var i in this) {
      if (this.hasOwnProperty(i))
        result[i] = fn(this[i], i, this);  // 3 arguments according to ECMA specs
    }
    return result;
};

(一部の言語ではcollect別の名前であるため、コードを試すために使用されます)map

4

2 に答える 2

3

簡単なはずですが、いくつかの特徴があります。

コールバック関数は、問題の配列を変更できます。追加または削除する要素にはアクセスしません。したがって、Object.keysのようなものを使用して、アクセスする要素を決定する必要があるようです。

また、結果は、古い配列の長さをとる配列コンストラクターによって「作成されたかのように」新しい配列として定義されるため、そのコンストラクターを使用して作成することもできます。

これらのことを考慮した実装がありますが、おそらく他の微妙な点が欠けています。

function map(callbackfn, thisArg) {
  var keys = Object.keys(this),
    result = new Array(this.length);

  keys.forEach(function(key) {
    if (key >= 0 && this.hasOwnProperty(key)) {
      result[key] = callbackfn.call(thisArg, this[key], key, this);
    }
  }, this);

  return result;
}

Object.keysが配列のキーを番号順に返すと仮定しています。これは、実装で定義されていると思います。そうでない場合は、それらを並べ替えることができます。

于 2012-10-10T15:00:45.370 に答える
0

を使用する必要はありませんthis.slice(0)。配列を作成resultして、任意のインデックスに値を割り当てることができます。

Array.prototype.collect = Array.prototype.collect || function(fn) { 
  var result = [];
  for(var i in this) {
    if (this.hasOwnProperty(i)) { 
      result[i] = fn(this[i]);
    }
  }
  return result;
}
于 2012-10-10T14:30:54.300 に答える