変換する必要はありませんMap
にはArray
。あなたは単にオブジェクトを作成map
してfilter
機能させることができMap
ます:
function map(functor, object, self) {
var result = new Map;
object.forEach(function (value, key, object) {
result.set(key, functor.call(this, value, key, object));
}, self);
return result;
}
function filter(predicate, object, self) {
var result = new Map;
object.forEach(function (value, key, object) {
if (predicate.call(this, value, key, object)) result.set(key, value);
}, self);
return result;
}
たとえば!
、キーがプリミティブであるマップの各エントリの値にバング(文字)を追加できます。
var object = new Map;
object.set("", "empty string");
object.set(0, "number zero");
object.set(object, "itself");
var result = map(appendBang, filter(primitive, object));
alert(result.get("")); // empty string!
alert(result.get(0)); // number zero!
alert(result.get(object)); // undefined
function primitive(value, key) {
return isPrimitive(key);
}
function appendBang(value) {
return value + "!";
}
function isPrimitive(value) {
var type = typeof value;
return value === null ||
type !== "object" &&
type !== "function";
}
<script>
function map(functor, object, self) {
var result = new Map;
object.forEach(function (value, key, object) {
result.set(key, functor.call(this, value, key, object));
}, self || null);
return result;
}
function filter(predicate, object, self) {
var result = new Map;
object.forEach(function (value, key, object) {
if (predicate.call(this, value, key, object)) result.set(key, value);
}, self || null);
return result;
}
</script>
またmap
、filter
メソッドを追加しMap.prototype
て読みやすくすることもできます。一般的にはまだ本来のプロトタイプを変更することをお勧めされていないが、私は、例外がある場合に行うことができることを信じているmap
とfilter
のためにMap.prototype
:
var object = new Map;
object.set("", "empty string");
object.set(0, "number zero");
object.set(object, "itself");
var result = object.filter(primitive).map(appendBang);
alert(result.get("")); // empty string!
alert(result.get(0)); // number zero!
alert(result.get(object)); // undefined
function primitive(value, key) {
return isPrimitive(key);
}
function appendBang(value) {
return value + "!";
}
function isPrimitive(value) {
var type = typeof value;
return value === null ||
type !== "object" &&
type !== "function";
}
<script>
Map.prototype.map = function (functor, self) {
var result = new Map;
this.forEach(function (value, key, object) {
result.set(key, functor.call(this, value, key, object));
}, self || null);
return result;
};
Map.prototype.filter = function (predicate, self) {
var result = new Map;
this.forEach(function (value, key, object) {
if (predicate.call(this, value, key, object)) result.set(key, value);
}, self || null);
return result;
};
</script>
編集: Bergiの回答では、彼はすべての反復可能なオブジェクトのジェネリック関数map
とfilter
ジェネレーター関数を作成しました。それらを使用する利点は、それらがジェネレーター関数であるため、中間の反復可能なオブジェクトを割り当てないことです。
たとえば、上で定義したmy map
およびfilter
functions は、新しいMap
オブジェクトを作成します。したがって、呼び出しobject.filter(primitive).map(appendBang)
により2つの新しいMap
オブジェクトが作成されます。
var intermediate = object.filter(primitive);
var result = intermediate.map(appendBang);
中間の反復可能オブジェクトの作成にはコストがかかります。Bergiのジェネレーター関数はこの問題を解決します。これらは中間オブジェクトを割り当てませんが、1つのイテレータがその値を遅延して次のオブジェクトにフィードできるようにします。この種の最適化は、関数型プログラミング言語ではフュージョンまたは森林破壊と呼ばれ、プログラムのパフォーマンスを大幅に向上させることができます。
Bergiのジェネレーター関数で私が持っている唯一の問題は、それらがMap
オブジェクトに固有ではないことです。代わりに、すべての反復可能なオブジェクトに対して一般化されます。したがって、コールバック関数を(value, key)
ペアで呼び出すのではなく(私がをマッピングするときに予想するようにMap
)、(value, index)
ペアでコールバック関数を呼び出します。そうでなければ、それは優れたソリューションであり、私が提供したソリューションよりも使用することをお勧めします。
したがって、これらは、Map
オブジェクトのマッピングとフィルタリングに使用する特定のジェネレーター関数です。
function * map(functor, entries, self) {
var that = self || null;
for (var entry of entries) {
var key = entry[0];
var value = entry[1];
yield [key, functor.call(that, value, key, entries)];
}
}
function * filter(predicate, entries, self) {
var that = self || null;
for (var entry of entries) {
var key = entry[0];
var value = entry[1];
if (predicate.call(that, value, key, entries)) yield [key, value];
}
}
function toMap(entries) {
var result = new Map;
for (var entry of entries) {
var key = entry[0];
var value = entry[1];
result.set(key, value);
}
return result;
}
function toArray(entries) {
var array = [];
for (var entry of entries) {
array.push(entry[1]);
}
return array;
}
次のように使用できます。
var object = new Map;
object.set("", "empty string");
object.set(0, "number zero");
object.set(object, "itself");
var result = toMap(map(appendBang, filter(primitive, object.entries())));
alert(result.get("")); // empty string!
alert(result.get(0)); // number zero!
alert(result.get(object)); // undefined
var array = toArray(map(appendBang, filter(primitive, object.entries())));
alert(JSON.stringify(array, null, 4));
function primitive(value, key) {
return isPrimitive(key);
}
function appendBang(value) {
return value + "!";
}
function isPrimitive(value) {
var type = typeof value;
return value === null ||
type !== "object" &&
type !== "function";
}
<script>
function * map(functor, entries, self) {
var that = self || null;
for (var entry of entries) {
var key = entry[0];
var value = entry[1];
yield [key, functor.call(that, value, key, entries)];
}
}
function * filter(predicate, entries, self) {
var that = self || null;
for (var entry of entries) {
var key = entry[0];
var value = entry[1];
if (predicate.call(that, value, key, entries)) yield [key, value];
}
}
function toMap(entries) {
var result = new Map;
for (var entry of entries) {
var key = entry[0];
var value = entry[1];
result.set(key, value);
}
return result;
}
function toArray(entries) {
var array = [];
for (var entry of entries) {
array.push(entry[1]);
}
return array;
}
</script>
より流暢なインターフェイスが必要な場合は、次のようにすることができます。
var object = new Map;
object.set("", "empty string");
object.set(0, "number zero");
object.set(object, "itself");
var result = new MapEntries(object).filter(primitive).map(appendBang).toMap();
alert(result.get("")); // empty string!
alert(result.get(0)); // number zero!
alert(result.get(object)); // undefined
var array = new MapEntries(object).filter(primitive).map(appendBang).toArray();
alert(JSON.stringify(array, null, 4));
function primitive(value, key) {
return isPrimitive(key);
}
function appendBang(value) {
return value + "!";
}
function isPrimitive(value) {
var type = typeof value;
return value === null ||
type !== "object" &&
type !== "function";
}
<script>
MapEntries.prototype = {
constructor: MapEntries,
map: function (functor, self) {
return new MapEntries(map(functor, this.entries, self), true);
},
filter: function (predicate, self) {
return new MapEntries(filter(predicate, this.entries, self), true);
},
toMap: function () {
return toMap(this.entries);
},
toArray: function () {
return toArray(this.entries);
}
};
function MapEntries(map, entries) {
this.entries = entries ? map : map.entries();
}
function * map(functor, entries, self) {
var that = self || null;
for (var entry of entries) {
var key = entry[0];
var value = entry[1];
yield [key, functor.call(that, value, key, entries)];
}
}
function * filter(predicate, entries, self) {
var that = self || null;
for (var entry of entries) {
var key = entry[0];
var value = entry[1];
if (predicate.call(that, value, key, entries)) yield [key, value];
}
}
function toMap(entries) {
var result = new Map;
for (var entry of entries) {
var key = entry[0];
var value = entry[1];
result.set(key, value);
}
return result;
}
function toArray(entries) {
var array = [];
for (var entry of entries) {
array.push(entry[1]);
}
return array;
}
</script>
お役に立てば幸いです。