Given the following array, I need to reduce it by employee function names and also sum a few rows.
Reduce if Row[1] is equal with any other, and sum Row[2] and Row[5].
example array
[
[ 20, 'AJUDANTE GERAL ', 2, 'HH', 6.36, 12.72, '', '' ],
[ 20, 'AJUDANTE GERAL ', 8, 'HH', 6.36, 50.88, '', '' ],
[ 20, 'AJUDANTE GERAL ', 0.15, 'HH', 6.36, 0.954, '', '' ],
[ 20, 'AJUDANTE GERAL ', 8, 'HH', 6.36, 50.88, '', '' ],
[ 125, 'CALDEREIRO', 8, 'HH', 13.05, 104.4, '', '' ],
[ 0, 'ISOLADOR', 2, 'HH', 10.68, 21.36, '', '' ],
[ 0, 'ISOLADOR', 8, 'HH', 10.68, 85.44, '', '' ],
[ 0, 'ISOLADOR', 0.15, 'HH', 10.68, 1.6019999999999999, '', '' ],
[ 585, 'PINTOR', 2, 'HH', 10.91, 21.82, '', '' ]
]
result expected
[
[ 20, 'AJUDANTE GERAL ', 18.15, 'HH', 6.36, 115.434, '', '' ],
[ 125, 'CALDEREIRO', 8, 'HH', 13.05, 104.4, '', '' ],
[ 0, 'ISOLADOR', 10.15, 'HH', 10.68, 108.402, '', '' ],
[ 585, 'PINTOR', 2, 'HH', 10.91, 21.82, '', '' ]
]
I was able to achieve this using a few for loops
which I believe it is not the real deal, since I am changing values during the loop. It is working, however, I would like to understand how could I do it with reduces and maps.
// sheetMapped is the array with all data duplicated
// uniqueRows is where I am keeping only the unique values with the sum values
let uniqueRows = [];
for (let i = 0; i < sheetMapped.length; i = 1) {
let row = sheetMapped[i];
let found = false;
for (let j = 0; j < uniqueRows.length; j = 1) {
let rowUniqueTest = uniqueRows[j];
if (row[1] === rowUniqueTest[1]) {
found = true;
uniqueRows[j][2] = row[2];
uniqueRows[j][5] = row[5];
break;
}
}
if (!found) {
uniqueRows.push(row);
}
}
I already tried a few examples using Array.from
, set Maps
, reduces
, but they were a bit hard to understand since I am working with more data in array and not just key/value pairs
.
Thanks in advance
CodePudding user response:
This can be done with a fairly standard 'group by' operation using reduce()
.
The snippet below uses a Map
as it maintains insertion order where as an object sorts numeric properties. The resulting Map
is converted back to an array using Array.from()
called on the Map.values()
const input = [ [ 20, 'AJUDANTE GERAL ', 2, 'HH', 6.36, 12.72, '', '' ], [ 20, 'AJUDANTE GERAL ', 8, 'HH', 6.36, 50.88, '', '' ], [ 20, 'AJUDANTE GERAL ', 0.15, 'HH', 6.36, 0.954, '', '' ], [ 20, 'AJUDANTE GERAL ', 8, 'HH', 6.36, 50.88, '', '' ], [ 125, 'CALDEREIRO', 8, 'HH', 13.05, 104.4, '', '' ], [ 0, 'ISOLADOR', 2, 'HH', 10.68, 21.36, '', '' ], [ 0, 'ISOLADOR', 8, 'HH', 10.68, 85.44, '', '' ], [ 0, 'ISOLADOR', 0.15, 'HH', 10.68, 1.6019999999999999, '', '' ], [ 585, 'PINTOR', 2, 'HH', 10.91, 21.82, '', '' ], ];
const result = Array.from(
input
.reduce((a, row) => {
if (!a.has(row[1])) {
a.set(row[1], [...row]);
} else {
const _row = a.get(row[1]);
_row[2] = row[2];
_row[5] = row[5];
}
return a;
}, new Map())
.values()
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
with an array as accumulator in reduce
this is a piece of cake take a look at below code
var data = [
[ 20, 'AJUDANTE GERAL ', 2, 'HH', 6.36, 12.72, '', '' ],
[ 20, 'AJUDANTE GERAL ', 8, 'HH', 6.36, 50.88, '', '' ],
[ 20, 'AJUDANTE GERAL ', 0.15, 'HH', 6.36, 0.954, '', '' ],
[ 20, 'AJUDANTE GERAL ', 8, 'HH', 6.36, 50.88, '', '' ],
[ 125, 'CALDEREIRO', 8, 'HH', 13.05, 104.4, '', '' ],
[ 0, 'ISOLADOR', 2, 'HH', 10.68, 21.36, '', '' ],
[ 0, 'ISOLADOR', 8, 'HH', 10.68, 85.44, '', '' ],
[ 0, 'ISOLADOR', 0.15, 'HH', 10.68, 1.6019999999999999, '', '' ],
[ 585, 'PINTOR', 2, 'HH', 10.91, 21.82, '', '' ]
]
data = data.reduce((a,e)=>{
let sInd = a.findIndex(each=>each.indexOf(e[1]) != -1)
if(sInd >= 0){ // if entry added already
a[sInd][2] = e[2]
a[sInd][5] = e[5]
}
else{a.push(e)} // if new entry
return a
},[])
console.log(data.join("\n"))
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
If row and col are fixed, You can use below sample code. Merge as an object and get all values.
const data = [
[20, "AJUDANTE GERAL ", 2, "HH", 6.36, 12.72, "", ""],[20, "AJUDANTE GERAL ", 8, "HH", 6.36, 50.88, "", ""],[20, "AJUDANTE GERAL ", 0.15, "HH", 6.36, 0.954, "", ""],[20, "AJUDANTE GERAL ", 8, "HH", 6.36, 50.88, "", ""],
[125, "CALDEREIRO", 8, "HH", 13.05, 104.4, "", ""],
[0, "ISOLADOR", 2, "HH", 10.68, 21.36, "", ""],[0, "ISOLADOR", 8, "HH", 10.68, 85.44, "", ""],[0, "ISOLADOR", 0.15, "HH", 10.68, 1.6019999999999999, "", ""],[585, "PINTOR", 2, "HH", 10.91, 21.82, "", ""],
];
const map = data.reduce((m, row) => {
const id = row[0];
if (id in m) {
m[id][2] = row[2];
m[id][5] = row[5];
} else {
m[id] = row;
}
return m;
}, {});
console.log(Object.values(map));
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>