My Array (can have several items, and there can be multiple 'keys' other than 'companyName'):
myarray = [
{ companyName: 'X', randomKey: 10, randomKey2: 90, ...},
{ companyName: 'X', randomKey: 30, randomKey2: 81, ...},
{ companyName: 'X', randomKey: 930, randomKey2: 93, ...},
{ companyName: 'X', randomKey: 20, randomKey2: 23, ...},
{ companyName: 'X', randomKey: 10, randomKey2: 10, ...},
{ companyName: 'X', randomKey: 11, randomKey2: 40, ...},
....
]
randomKey and randomKey2 are only examples. The key names can be anything and there can be 1 or more in each array item.
Expected results:
[
{ companyName: 'X', randomKey: 1011, randomKey2: 337, ...},
]
companyName: 'X' is a fixed value, and all of the items have this
Attempted:
this.myarray.reduce((acc, curr) => {
let ind = b.findIndex(e => e.companyName === curr.companyName);
if (ind > -1) {
acc[ind][c] = acc[ind][c] a[c]
} else {
a[c] = a[c] || 0
acc.push(curr)
}
return b;
}, []);
But it leads to [{x: NaN}].
How can I fix this?
CodePudding user response:
As to why your code is not working: you're not iterating over the object keys anywhere. There is reference to a variable c
, but it's never defined.
Probably easier to reduce to an accumulator object first:
const data = [
{ companyName: 'X', randomKey: 10, randomKey2: 90 },
{ companyName: 'X', randomKey: 30, randomKey2: 81 },
{ companyName: 'X', randomKey: 930, randomKey2: 93 },
{ companyName: 'X', randomKey: 20, randomKey2: 23 },
{ companyName: 'X', randomKey: 10, randomKey2: 10 },
{ companyName: 'X', randomKey: 11, randomKey2: 40 },
];
const fn = (data) => Object.values(
data.reduce((a, {companyName, ...rest}) => {
const entry = a[companyName] ??= { companyName };
Object.entries(rest).forEach(([k, v]) => entry[k] = (entry[k] ?? 0) v);
return a;
}, {})
);
console.log(fn(data));
CodePudding user response:
You can play around with this example
const myArray = [
{ companyName: 'X', randomKey: 10, randomKey2: 90 },
{ companyName: 'X', randomKey: 30, randomKey2: 81 },
{ companyName: 'X', randomKey: 930, randomKey2: 93 },
{ companyName: 'X', randomKey: 20, randomKey2: 23 },
{ companyName: 'X', randomKey: 10, randomKey2: 10 },
{ companyName: 'X', randomKey: 11, randomKey2: 40 },
{ companyName: 'Y', randomKey: 11, randomKey2: 45, randomKey3: 4 },
{ companyName: 'Y', randomKey: 21, randomKey2: 46 },
];
const results = {};
const addKeyValue = (target, data) => {
const keys = [...new Set([...Object.keys(target), ...Object.keys(data)])];
keys.forEach((key) => {
target[key] = target[key] || 0;
target[key] = data[key] || 0;
});
return target;
};
myArray.forEach(({ companyName, ...data }) => {
if (results[companyName] === undefined) {
results[companyName] = { ...data };
} else {
results[companyName] = addKeyValue(results[companyName], data);
}
});
console.log(results);
https://jsfiddle.net/gre6Ly1a/1/
CodePudding user response:
myarray = [
{ companyName: 'X', randomKey: 10, randomKey2: 90},
{ companyName: 'X', randomKey: 30, randomKey2: 81},
{ companyName: 'X', randomKey: 930, randomKey2: 93},
{ companyName: 'X', randomKey: 20, randomKey2: 23},
{ companyName: 'X', randomKey: 10, randomKey2: 10},
{ companyName: 'X', randomKey: 11, randomKey2: 40}
]
const b = myarray.reduce((acc, curr)=>{
let properties = {};
for(let key in curr){
if(acc[key] && acc[key] !== 'X') properties[key] = acc[key] curr[key]
}
return {...acc, ...curr, ...properties}
}, {})
console.log(b)
As already stated, it would probably be easier to ensure that the accumulator is initially an object. But this example will also work like the others above
CodePudding user response:
Presented below is one possible way to achieve the desired objective.
Code Snippet
const myTransform = (arr, col) => (
Object.values( // extract only values from the result below
arr.reduce( // use ".reduce()" to iterate over the array
(acc, itm) => { // "acc" is the accumulator, "itm" is the iterator
const k = itm[col] || null; // gather the "key" (ie, "X" from "companyName")
acc[k] ??= { [col]: k }; // set-up accumulator for "X"
Object.entries(itm) // iterate over the "itm"
.filter(([key, _]) => key !== col) // discard "companyName"
.forEach(([key, val]) => { // sum each key from "itm" into accumulator
acc[k][key] ??= 0; // initialize accumulator "X.randomKey/2" to 0
acc[k][key] = val; // transform "val" into a number (ie, val) & add
});
return acc; // return the accumulator at each iteration
},
{} // initialize the accumulator as an empty object
)
) // implicit return of the values array
);
const myArray = [
{ companyName: 'X', randomKey: 10, randomKey2: 90},
{ companyName: 'X', randomKey: 30, randomKey2: 81},
{ companyName: 'X', randomKey: 930, randomKey2: 93},
{ companyName: 'X', randomKey: 20, randomKey2: 23},
{ companyName: 'X', randomKey: 10, randomKey2: 10},
{ companyName: 'X', randomKey: 11, randomKey2: 40},
];
console.log(myTransform(myArray, 'companyName'));
console.log(
'test case 2 - with updated input array\n',
myTransform(
myArray.concat([
{ companyName: 'Y', randomKey: 100, randomKey4: 60},
{ companyName: 'Y', randomKey: 101, randomKey4: 141}
]),
'companyName'
)
);
.as-console-wrapper { max-height: 100% !important; top: 0 }
Explanation
Inline comments added to the snippet above.
CodePudding user response:
const data = [
{ companyName: 'X', randomKey: 10, randomKey2: 90 },
{ companyName: 'X', randomKey: 30, randomKey2: 81 },
{ companyName: 'X', randomKey: 930, randomKey2: 93 },
{ companyName: 'X', randomKey: 20, randomKey2: 23 },
{ companyName: 'X', randomKey: 10, randomKey2: 10 },
{ companyName: 'X', randomKey: 11, randomKey2: 40 },
];
let k;
const agg = data.map((o) => Object.keys(o).map((key) => {return {[key]:o[key]};})).flat().reduce((a,b) => {
k = Object.keys(b)[0];
a[k] = a[k] ? a[k] b[k] : b[k];
return a;
})
console.log(agg);