Там нет необходимости превращать 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>
Редактировать: В ответе Берги он создал универсальные map
и filter
генераторные функции для всех итерируемых объектов. Преимущество их использования состоит в том, что, поскольку они являются функциями генератора, они не выделяют промежуточные итерируемые объекты.
Например, функции my map
и filter
определенные выше создают новые Map
объекты. Следовательно, вызов object.filter(primitive).map(appendBang)
создает два новых Map
объекта:
var intermediate = object.filter(primitive);
var result = intermediate.map(appendBang);
Создание промежуточных итерируемых объектов стоит дорого. Функции генератора Берги решают эту проблему. Они не распределяют промежуточные объекты, но позволяют одному итератору лениво передавать свои значения следующему. Этот вид оптимизации известен как слияние или вырубка лесов в функциональных языках программирования, и он может значительно улучшить производительность программы.
Единственная проблема, с которой я сталкиваюсь с функциями генератора Берги, заключается в том, что они не являются специфичными для Map
объектов. Вместо этого они обобщаются для всех итерируемых объектов. Следовательно, вместо вызова функций обратного вызова с (value, key)
парами (как и следовало ожидать при отображении через a 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>
Надеюсь, это поможет.