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

206
Views
Js: ¿Cuál es la forma más eficiente de clasificar una matriz de objetos en secciones?

Tengo una gran variedad de objetos, similar a esto:

 [ { id: "some_id", timestamp: 12345 }, { id: "some_other_id", timestamp: 12347 }, { id: "some_id", timestamp: 12346 }, { id: "some_other_id", timestamp: 12348 }, ... ]

Quiero ordenar la matriz de manera que haya "secciones" de objetos en la matriz, según la identificación que tenga el objeto. Dentro de cada sección, los objetos deben ordenarse de forma ascendente según la marca de tiempo. Las secciones en sí también deben ordenarse según la primera marca de tiempo de la sección. Entonces la matriz debería verse así:

 [ // section: some_id { id: "some_id", timestamp: 12345 }, { id: "some_id", timestamp: 12348 }, // section: some_other_id, comes ofter some_id section because 12346 > 12345 { id: "some_other_id", timestamp: 12346 }, { id: "some_other_id", timestamp: 12347 }, ... ]

También debería ser posible elegir entre ascender/descender en la función. Ahora mismo tengo esto:

 elements.sort((a, b) => { if (a.id === b.id) { if (sortAscending) { return a.timestamp > b.timestamp ? -1 : 1; } else { return a.timestamp > b.timestamp ? 1 : -1; } } else { return a.id.localeCompare(b.id); } })

Sin embargo, esto no ordena las secciones correctamente. ¿Algunas ideas?

about 4 years ago · Juan Pablo Isaza
3 answers
Answer question

0

No vas a poder hacerlo de una sola manera. Tendrá que ser varios pasos ya que no sabe cuál es el mínimo.

Una forma es combinar, ordenar y luego ordenar según el más bajo.

 const data = [ { id: "a", timestamp: 4 }, { id: "b", timestamp: 3 }, { id: "a", timestamp: 2 }, { id: "b", timestamp: 1 }, ]; const x = data.reduce((a,o) => { a[o.id] = a[o.id] || []; a[o.id].push(o); return a; }, {}); const v = Object.values(x); v.forEach(x => x.sort((a,b) => a.timestamp > b.timestamp ? 1 : -1)) v.sort((a,b)=>a[0].timestamp > b[0].timestamp ? 1 : -1); const sorted = v.flat(); console.log(sorted);

La otra forma es encontrar el más bajo y luego ordenarlo.

 const data = [{ id: "a", timestamp: 4 }, { id: "b", timestamp: 3 }, { id: "a", timestamp: 2 }, { id: "b", timestamp: 1 }, ]; const smallest = data.reduce((a ,o) => { a[o.id] = Math.min(a[o.id] === undefined? Number.POSITIVE_INFINITY : a[o.id], o.timestamp); return a; }, {}); data.sort((a,b) => { return a.id === b.id ? (a.timestamp > b.timestamp ? 1 : -1) : smallest[a.id] > smallest[b.id] ? 1 : -1; }) console.log(data);

about 4 years ago · Juan Pablo Isaza Report

0

Esto requerirá dos pasadas a través de la matriz porque no puede ordenar por secciones hasta que sepa cuál debe ser el orden de las secciones y no lo sabrá hasta que haya visto todas las secciones y, por lo tanto, sepa cuál es la más baja o la más alta. la marca de tiempo es para cada sección (dependiendo de si está haciendo una ordenación ascendente o descendente).

Entonces, probablemente lo que tiene sentido es hacer un primer paso que recopile el valor extremo de cada sección y lo almacene en un objeto Map que puede usar como índice de clasificación de sección. Luego, puede ejecutar .sort() . Si las secciones son iguales, ordena por marca de tiempo. Si las secciones no son iguales, ordena por el valor en el índice de la sección.

 function sortByIdAndTimestamp(data, sortAscending = true) { // create a Map object where keys are id values and values are the extreme // timestamp for that id const extremeTimestamp = new Map(); for (let item of data) { if (testExtreme(item.timestamp, extremeTimestamp.get(item.id), sortAscending)) { extremeTimestamp.set(item.id, item.timestamp); } } // now just do a dual key sort data.sort((a, b) => { let result; if (a.id === b.id) { // if id is the same, just sort by timestamp result = b.timestamp - a.timestamp; } else { // if id is not the same, sort by the extreme timestamp of the id result = extremeTimestamp.get(b.id) - extremeTimestamp.get(a.id); } if (sortAscending) { result = -result; } return result; }); return data; } function testExtreme(val, extremeSoFar, sortAscending) { // determine if this id's timestamp is more extreme // than what we already have for that section return (extremeSoFar === undefined) || (sortAscending ? val < extremeSoFar : val > extremeSoFar); } const sampleData = [{ id: "some_id", timestamp: 12345 }, { id: "some_other_id", timestamp: 123 }, { id: "some_id", timestamp: 12346 }, { id: "some_other_id", timestamp: 99999 }, { id: "yet_another_id", timestamp: 1 }, { id: "yet_another_id", timestamp: 90000 }, ]; sortByIdAndTimestamp(sampleData, true); console.log(sampleData);

Nota: Cuando dijiste que querías ordenar en orden ascendente o descendente, supuse que te referías a ambas secciones y a las marcas de tiempo. Por lo tanto, una ordenación ascendente tendría primero la sección de marca de tiempo más baja y luego los elementos dentro de cada sección se ordenarían por marca de tiempo de menor a mayor. Y, una ordenación descendente tendría primero la sección de marca de tiempo más alta y luego los elementos dentro de cada sección se ordenarían por marca de tiempo de mayor a menor.

about 4 years ago · Juan Pablo Isaza Report

0

EDITADO: aquí hay una forma de hacerlo si entendí correctamente lo que necesita

 const data = [{ id: "some_id", timestamp: 12348 }, { id: "some_other_id", timestamp: 12346 }, { id: "some_id", timestamp: 12345 }, { id: "some_other_id", timestamp: 12347 }, { id: "X_other_id", timestamp: 12343 }, { id: "other_id", timestamp: 12349 } ] const groupById = (acc, item) => { acc[item.id] ? acc[item.id].push(item) : acc[item.id] = [item]; return acc; }; function sort(arr, bool) { const groups = Object.values(arr.reduce(groupById, {})) .map(group => group.sort((a, b) => bool ? a.timestamp - b.timestamp : b.timestamp - a.timestamp)) .sort((a, b) => bool ? a[0].timestamp - b[0].timestamp : b[0].timestamp - a[0].timestamp); return groups.flat() } console.log(sort(data, ascending = true))

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!