Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

306
Vistas
Usando reduce, ¿cómo hacer un directorio de objetos donde cada clave sea un valor único y almacene valores repetidos como subobjetos?

¿Cómo creo una función usando reduce que tomará una matriz de objetos y devolverá un directorio de objetos con claves únicas, pero que permita valores repetidos?

  1. cada clave es el nombre de la persona
  2. cada tecla repetida tiene una matriz anidada con un directorio de números
  3. si no hay claves repetidas, la clave debe contener solo un objeto

Me gustaría que la salida se viera así:

 { Bob: { '0': { name: 'Bob', age: 30, voted: true }, '1': { name: 'Bob', age: 31, voted: true }, '2': { name: 'Bob', age: 32, voted: true }, }, Jake: { '0': { name: 'Jake', age: 20, voted: false }, '1': { name: 'Jake', age: 32, voted: true } }, Phil: { name: 'Phil', age: 21, voted: true }, Ed: { name: 'Ed', age: 55, voted: true }, Tami: { name: 'Tami', age: 54, voted: true }, Mary: { name: 'Mary', age: 31, voted: false }, Becky: { name: 'Becky', age: 43, voted: false }, Joey: { name: 'Joey', age: 41, voted: true }, Jeff: { name: 'Jeff', age: 30, voted: true }, Zack: { name: 'Zack', age: 19, voted: false } }

Este es mi código, los resultados se comen entre sí si ocurren dos nombres repetidos, y distribuye el primer objeto en la clave sin agregarle una clave numérica.

 let count = 0 const toNamedObj = (arr) => { return arr.reduce((acc, cur) => { let key = Object.values(cur)[0] if(acc.hasOwnProperty(key)){ count ++ console.log(count) return {[key]: {...acc[key], [count]: cur} } } return {...acc, [key]: cur} } ,{}) } const voters = [ {name:'Bob' , age: 30, voted: true}, {name:'Bob' , age: 31, voted: true}, {name:'Bob' , age: 32, voted: true}, {name:'Jake' , age: 32, voted: true}, {name:'Kate' , age: 25, voted: false}, {name:'Jake' , age: 20, voted: false}, {name:'Phil' , age: 21, voted: true}, {name:'Ed' , age:55, voted:true}, {name:'Tami' , age: 54, voted:true}, {name: 'Mary', age: 31, voted: false}, {name: 'Becky', age: 43, voted: false}, {name: 'Joey', age: 41, voted: true}, {name: 'Jeff', age: 30, voted: true}, {name: 'Zack', age: 19, voted: false} ]; console.log(toNamedObj(voters));

about 4 years ago · Juan Pablo Isaza
2 Respuestas
Responde la pregunta

0

Usando su enfoque actual, debería poder detectar, al iterar, si el nombre ya existe, si el objeto anidado en él es un objeto de votante simple (en cuyo caso tendría que eliminarse y reemplazarse con el objeto similar a una matriz), o si es el objeto similar a una matriz. Si bien eso sería posible , sería complicado. Un mejor enfoque sería agrupar incondicionalmente en matrices indexadas por nombre y luego transformar cada matriz en el objeto de votante único o en el objeto {0: .. 1: } después.

 const toNamedObj = (arr) => { const votersByName = {}; for (const voter of voters) { votersByName[voter.name] ??= []; votersByName[voter.name].push(voter); } for (const [name, voters] of Object.entries(votersByName)) { votersByName[name] = voters.length === 1 ? voters[0] : { ...voters }; } return votersByName; } const voters = [ {name:'Bob' , age: 30, voted: true}, {name:'Bob' , age: 31, voted: true}, {name:'Bob' , age: 32, voted: true}, {name:'Jake' , age: 32, voted: true}, {name:'Kate' , age: 25, voted: false}, {name:'Jake' , age: 20, voted: false}, {name:'Phil' , age: 21, voted: true}, {name:'Ed' , age:55, voted:true}, {name:'Tami' , age: 54, voted:true}, {name: 'Mary', age: 31, voted: false}, {name: 'Becky', age: 43, voted: false}, {name: 'Joey', age: 41, voted: true}, {name: 'Jeff', age: 30, voted: true}, {name: 'Zack', age: 19, voted: false} ]; console.log(toNamedObj(voters));

O mapeando las entradas

 const toNamedObj = (arr) => { const votersByName = {}; for (const voter of voters) { votersByName[voter.name] ??= []; votersByName[voter.name].push(voter); } return Object.fromEntries( Object.entries(votersByName) .map(([name, voters]) => ([ name, voters.length === 1 ? voters[0] : { ...voters } ])) ); } const voters = [ {name:'Bob' , age: 30, voted: true}, {name:'Bob' , age: 31, voted: true}, {name:'Bob' , age: 32, voted: true}, {name:'Jake' , age: 32, voted: true}, {name:'Kate' , age: 25, voted: false}, {name:'Jake' , age: 20, voted: false}, {name:'Phil' , age: 21, voted: true}, {name:'Ed' , age:55, voted:true}, {name:'Tami' , age: 54, voted:true}, {name: 'Mary', age: 31, voted: false}, {name: 'Becky', age: 43, voted: false}, {name: 'Joey', age: 41, voted: true}, {name: 'Jeff', age: 30, voted: true}, {name: 'Zack', age: 19, voted: false} ]; console.log(toNamedObj(voters));

Recomiendo no usar .reduce cuando el acumulador tiene el mismo valor en cada iteración: un bucle simple es más fácil for escribir y comprender.

about 4 years ago · Juan Pablo Isaza Denunciar

0

A continuación se presenta una posible forma de lograr el objetivo deseado.

Fragmento de código

 // method to transform arr to desired format const toNamedObj = arr => ( arr.reduce( (acc, {name, voted, ...rest}, idx) => ( (acc[name] ??= []).push({ name, voted, ...rest }), (idx === arr.length - 1 && Object.entries(acc).forEach( ([k, v]) => (acc[k] = (v.length === 1) ? v[0] : {...v}) )), acc ), {} ) ); /* with explanation // method to transform arr to desired format const toNamedObj = arr => ( // iterate using ".reduce()" arr.reduce( (acc, {name, voted, ...rest}, idx) => { // if "name" not present in "acc", set it as empty array acc[name] ??= []; // push elt into array acc[name].push({ name, voted, ...rest }); // when iterating over the last item, special processing if (idx === arr.length - 1) { // processed last elt in arr // review each value in "acc" and convert to object Object.entries(acc) .forEach(([k, v]) => { if (v.length === 1) { // only one elt in value-array // place the elt as-is acc[k] = v[0]; } else { // multiple elts in val-arr // convert val-arr to object acc[k] = {...v}; } }); }; // always return the accumulator "acc" in ".reduce()" callback return acc; }, {} // "acc" is set as an empty object initially ) ); */ const voters = [ {name:'Bob' , age: 30, voted: true}, {name:'Bob' , age: 31, voted: true}, {name:'Bob' , age: 32, voted: true}, {name:'Jake' , age: 32, voted: true}, {name:'Kate' , age: 25, voted: false}, {name:'Jake' , age: 20, voted: false}, {name:'Phil' , age: 21, voted: true}, {name:'Ed' , age:55, voted:true}, {name:'Tami' , age: 54, voted:true}, {name: 'Mary', age: 31, voted: false}, {name: 'Becky', age: 43, voted: false}, {name: 'Joey', age: 41, voted: true}, {name: 'Jeff', age: 30, voted: true}, {name: 'Zack', age: 19, voted: false} ]; console.log(toNamedObj(voters));
 .as-console-wrapper { max-height: 100% !important; top: 0 }

Explicación

Se agregaron comentarios en línea al fragmento anterior.

about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda