Me gustaría obtener el máximo de cada tipo de factura utilizando el método de reducción. La función tiene que itirar y comparar cada elemento con el siguiente en la línea, luego, si los nombres coinciden (elemento [0]), debe comparar sus valores (elemento [1]) y almacenar el valor más grande con ese nombre original.
Quiero usar reduce para esto, pero me cuesta entender cómo se aplica exactamente el acumulador aquí. ¿Alguna sugerencia? :)
const tempCollected= [ ["TWENTY", 20], ["TWENTY", 40], ["TWENTY", 60], ["TEN", 10], ["TEN", 20], ["FIVE", 5], ["FIVE", 10], ["FIVE", 15], ["ONE", 1], ["QUARTER", 0.25], ["QUARTER", 0.5], ["DIME", 0.1], ["DIME", 0.2], ["PENNY", 0.01], ["PENNY", 0.02], ["PENNY", 0.03] ] /* Desired outcome using reduce [ ["TWENTY", 60], ["TEN", 20], ["FIVE", 15], ["ONE", 1], ["QUARTER", 0.5], ["DIME", 0.2], ["PENNY", 0.03] ] */ /*My try */ const attempt=tempCollected.reduce( (a,b,i,arr)=>{ if(b[i+1][0]===b[0]){ //if next item has the same name as the current return [...a,b[0],Math.max(b[1],b[i+1][1])] //return Math.max(...of those two) + the original name of the bill } return [...a,b] },[] )La forma en que parece configurarse el problema requiere una solución algo complicada, ya que en cada iteración, es posible que deba eliminar el elemento anterior en el acumulador, o puede que solo tenga que agregar un elemento.
const tempCollected= [ ["TWENTY", 20], ["TWENTY", 40], ["TWENTY", 60], ["TEN", 10], ["TEN", 20], ["FIVE", 5], ["FIVE", 10], ["FIVE", 15], ["ONE", 1], ["QUARTER", 0.25], ["QUARTER", 0.5], ["DIME", 0.1], ["DIME", 0.2], ["PENNY", 0.01], ["PENNY", 0.02], ["PENNY", 0.03] ]; const result = tempCollected.reduce((a, subarr) => { // if no items have been iterated over yet, or if the type is new, // push unconditionally if ( !a.length || ( a[a.length - 1][0] !== subarr[0] )) { a.push(subarr); return a; } // otherwise, remove the final item and push the new item // if the final item's value is greater if (subarr[1] > a[a.length - 1][1]) { a.pop(); a.push(subarr); } return a; }, []); console.log(result);Si no se requiere que el método de solución se reduzca a una matriz, sería mucho más fácil agruparlo convirtiéndolo en un objeto.
const tempCollected= [ ["TWENTY", 20], ["TWENTY", 40], ["TWENTY", 60], ["TEN", 10], ["TEN", 20], ["FIVE", 5], ["FIVE", 10], ["FIVE", 15], ["ONE", 1], ["QUARTER", 0.25], ["QUARTER", 0.5], ["DIME", 0.1], ["DIME", 0.2], ["PENNY", 0.01], ["PENNY", 0.02], ["PENNY", 0.03] ]; const grouped = {}; for (const [type, num] of tempCollected) { grouped[type] = Math.max((grouped[type] || 0), num); } const result = Object.entries(grouped); console.log(result);No creo que reduce sea el camino a seguir aquí (obviamente podría hacerse porque al final todavía está recorriendo la matriz, pero parece más un abuso del método). ¡No tengas miedo de hacer las cosas más detalladas! El código corto no significa mejor código.
Echa un vistazo al siguiente fragmento:
const data = [ ['TWENTY', 20], ['TWENTY', 40], ['TWENTY', 60], ['TEN', 10], ['TEN', 20], ['FIVE', 5], ['FIVE', 10], ['FIVE', 15], ['ONE', 1], ['QUARTER', 0.25], ['QUARTER', 0.5], ['DIME', 0.1], ['DIME', 0.2], ['PENNY', 0.01], ['PENNY', 0.02], ['PENNY', 0.03] ]; const group = (input) => { const output = new Map(); input.forEach((item) => { const [key, value] = item; output.set(key, Math.max(output.get(key) || -Infinity, value)); }); return Array.from(output.entries()); }; console.log(group(data)); Solo para completar, este sería el método de reduce 'abuso'. Esencialmente, se usa para almacenar el objeto o mapa de salida como el valor acumulado y el ciclo al mismo tiempo:
const data = [ ['TWENTY', 20], ['TWENTY', 40], ['TWENTY', 60], ['TEN', 10], ['TEN', 20], ['FIVE', 5], ['FIVE', 10], ['FIVE', 15], ['ONE', 1], ['QUARTER', 0.25], ['QUARTER', 0.5], ['DIME', 0.1], ['DIME', 0.2], ['PENNY', 0.01], ['PENNY', 0.02], ['PENNY', 0.03] ]; const result = data.reduce((acc, item, index, input) => { acc[item[0]] = Math.max(acc[item[0]] || -Infinity, item[1]); if (index < input.length - 1) { return acc; } else { return Object.entries(acc); } }, {}); console.log(result);Puede ser un oneliner usando Array.reduce para crear un objeto y convertir su resultado nuevamente en un Array con Object.entries . En el fragmento, la matriz inicial se baraja (sin ordenar), por lo que se agrega una ordenación adicional para ordenar el resultado de forma descendente en los valores de resultado. Tenga en cuenta que al usar este reductor lambda, el orden de los valores iniciales se ha vuelto irrelevante.
// shuffled the values a bit const temp = [ ["TWENTY", 60], ["FIVE", 5], ["PENNY", 0.03], ["TWENTY", 40], ["TEN", 10], ["QUARTER", 0.5], ["TEN", 20], ["FIVE", 10], ["ONE", 1], ["FIVE", 15], ["TWENTY", 20], ["QUARTER", 0.25], ["DIME", 0.1], ["PENNY", 0.01], ["DIME", 0.2], ["PENNY", 0.02], ]; const collectedMaxValues = Object.entries( temp.reduce( (acc, [key, val]) => ( {...acc, [key]: (acc[key] || 0) > val ? acc[key] : val } ), {} ) ).sort( ([,val1], [,val2]) => val2 - val1); console.log(JSON.stringify(collectedMaxValues));