Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

302
Views
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 answers
Answer question

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 Report

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 Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!