¿Hay alguna forma de map
/ reduce
/ filter
/ etc a Set
en JavaScript o tendré que escribir la mía?
Aquí hay algunas Set.prototype
extensiones sensatas
Set.prototype.map = function map(f) {
var newSet = new Set();
for (var v of this.values()) newSet.add(f(v));
return newSet;
};
Set.prototype.reduce = function(f,initial) {
var result = initial;
for (var v of this) result = f(result, v);
return result;
};
Set.prototype.filter = function filter(f) {
var newSet = new Set();
for (var v of this) if(f(v)) newSet.add(v);
return newSet;
};
Set.prototype.every = function every(f) {
for (var v of this) if (!f(v)) return false;
return true;
};
Set.prototype.some = function some(f) {
for (var v of this) if (f(v)) return true;
return false;
};
Tomemos un pequeño set
let s = new Set([1,2,3,4]);
Y algunas estúpidas funciones
const times10 = x => x * 10;
const add = (x,y) => x + y;
const even = x => x % 2 === 0;
Y mira cómo funcionan
s.map(times10); //=> Set {10,20,30,40}
s.reduce(add, 0); //=> 10
s.filter(even); //=> Set {2,4}
s.every(even); //=> false
s.some(even); //=> true
¿No es lindo? Sí, yo también lo creo. Compare eso con el uso del iterador feo
// puke
let newSet = new Set();
for (let v in s) {
newSet.add(times10(v));
}
Y
// barf
let sum = 0;
for (let v in s) {
sum = sum + v;
}
¿Hay alguna forma mejor de lograr map
y reduce
usar un Set
JavaScript?
javascript
set
ecmascript-6
reduce
Gracias
fuente
fuente
Set
es que los Conjuntos no son Functores.var s = new Set([1,2,3,4]); s.map((a) => 42);
. Cambia el número de elementos, quemap
normalmente no se supone que debe hacer. Peor aún si solo está comparando partes de los objetos guardados, porque técnicamente no se especifica cuál obtendrá.forEach
existe para ese escenario, pero ¿por qué noreduce
entonces?Respuestas:
Una forma abreviada de hacerlo es convertirlo en una matriz a través del operador de propagación ES6.
Entonces todas las funciones de la matriz están disponibles para usted.
fuente
Array.from
eso es queArray.from
funciona con TypeScript. El uso[...mySet]
da el error:TS2461: Type 'Set<number>' is not an array type.
@@iterator
método.ERROR TypeError: this.sausages.slice is not a function
Para resumir la discusión de los comentarios: si bien no hay razones técnicas para que el conjunto no tenga
reduce
, actualmente no se proporciona y solo podemos esperar que cambie en ES7.En cuanto a
map
, llamarlo solo podría violar elSet
restricción, por lo que su presencia aquí podría ser discutible.Considere mapear con una función
(a) => 42
: cambiará el tamaño del conjunto a 1, y esto podría o no ser lo que deseaba.Si está de acuerdo con violar eso porque, por ejemplo, va a doblar de todos modos, puede aplicar la
map
parte en cada elemento justo antes de pasarlosreduce
, aceptando así que la colección intermedia ( que no es un Conjunto en este punto ) es podría reducirse podría tener elementos duplicados. Esto es esencialmente equivalente a convertir a Array para hacer el procesamiento.fuente
s.map(a => 42)
resultará enSet { 42 }
que el resultado mapeado tendrá una longitud diferente pero no habrá elementos "duplicados". Tal vez actualice la redacción y aceptaré esta respuesta.La causa de la falta de
map
/reduce
/filter
enMap
/Set
colecciones parecen ser principalmente preocupaciones conceptuales. Si cada tipo de colección en Javascript especifica realmente sus propios métodos iterativos solo para permitir estoen vez de
Una alternativa era especificar map / reduce / filter como parte del protocolo iterable / iterator, ya que
entries
/values
/keys
returnIterator
s. Sin embargo, es concebible que no todos los iterables sean "mapeables". Otra alternativa era especificar un "protocolo de recolección" separado para este mismo propósito.Sin embargo, no conozco la discusión actual sobre este tema en ES.
fuente