Set<Value> registra pertenencia sin guardar un valor separado.
Ambos suelen estar implementados con hashing y ofrecen operaciones promedio cercanas a O(1), pero su valor principal es permitir que el modelo del algoritmo sea explícito.
Texto
¿ya lo vi? → Set
¿cuántas veces aparece? → Map<value, count>
¿dónde apareció? → Map<value, index>
¿qué resultado calculé? → Map<state, result>
Contar apariciones convierte búsquedas repetidas en una sola pasada.
TypeScript
functionfrequencies<T>(values:readonlyT[]): Map<T,number>{const counts =newMap<T,number>();for(const value of values){
counts.set(value,(counts.get(value)??0)+1);}return counts;}
Tiempo promedio: O(n). Memoria: O(k), donde k es la cantidad de valores distintos.
functionareAnagrams(a:string, b:string):boolean{const left =[...a];const right =[...b];if(left.length !== right.length)returnfalse;const counts =newMap<string,number>();for(const character of left){
counts.set(character,(counts.get(character)??0)+1);}for(const character of right){const count = counts.get(character);if(count ===undefined)returnfalse;if(count ===1){
counts.delete(character);}else{
counts.set(character, count -1);}}return counts.size ===0;}
[...text] recorre code points, pero no normaliza Unicode. Una aplicación real debe decidir si é precompuesto y e + acento son equivalentes.
Conserva la primera aparición según el orden de iteración del Set.
Para objetos por id:
TypeScript
functionuniqueById<Textends{ id:string}>(values:readonlyT[]):T[]{const seen =newSet<string>();const result:T[]=[];for(const value of values){if(seen.has(value.id))continue;
seen.add(value.id);
result.push(value);}return result;}
Debes decidir si conserva el primero, el último o combina duplicados.
functiongroupBy<K,T>(
values:readonlyT[],keyOf:(value:T)=>K,): Map<K,T[]>{const groups =newMap<K,T[]>();for(const value of values){const key =keyOf(value);const group = groups.get(key);if(group){
group.push(value);}else{
groups.set(key,[value]);}}return groups;}
Tiempo promedio O(n) más el costo de calcular la clave. Memoria O(n) para guardar referencias en grupos.
La clave debe incluir toda la información que cambia el resultado futuro.
Para un estado (index, remaining):
TypeScript
const key =`${index}:${remaining}`;
Esto es sencillo, pero debes evitar ambigüedades y costo excesivo de serialización. Para estados anidados, puedes usar Map<number, Map<number, Result>>.
Objetos como claves funcionan solo si reutilizas la misma identidad. Crear { index, remaining } en cada llamada no produce hits aunque los campos sean iguales.
Solo aceptan objetos como claves y no impiden que el garbage collector libere esas claves. No son iterables porque su contenido puede desaparecer según reachability.
Útiles para:
metadata privada asociada a objetos;
evitar retener objetos solo por una cache auxiliar.
No sirven cuando necesitas enumerar entradas o conocer tamaño.
Las operaciones de Map y Set suelen ser promedio o amortizadas cercanas a O(1). El estándar del lenguaje define comportamiento observable, no exige una implementación concreta de hash table ni garantiza peor caso constante.
Porque los objetos se comparan por identidad. Aunque tengan los mismos campos, son dos referencias distintas. Para deduplicar por id, debes almacenar esa clave o usar un Map indexado por ella.