I have a JSONLines file containing thousands of items and I need to merge all of them but for arrays instead of merge need to concatenate them. I don't have the item schema so need to dynamically do this.
{title: 'test', data: [1]}
{title: 'test', data: [2]}
{title: 'test1', data: [3]}
and output will be something like this
{title: 'test1', data: [1,2,3]}
not sure what is the best performing way I can do.
CodePudding user response:
No so complicated You can separate the steps. Like:
const array = [
{ title: 'test', data: [1], data2: ['data1', 'data2'] },
{ title: 'test', data: [2], data2: [1, 2] },
{ title: 'test1', data: [3], data2: [1, 2, 3] },
{ title: 'test1', data2: [1, 2, 3] },
{ title: 'test1', data2: 'string' },
{ title: 'test3', data2: 69 },
];
const mergeAllKeys = (newArr, val, ix, mergeOn) => {
return Object.keys(newArr[ix])
.filter((k) => k !== mergeOn)
.reduce((obj, k) => ({
...obj,
[k]: [
...newArr[ix][k],
...(Array.isArray(val[k]) ? val[k] : [val[k]]),
].filter((v) => v),
}), {});
};
const keysToArray = (val, mergeOn) => {
return Object.keys(val)
.filter((k) => k !== mergeOn)
.reduce((o, k) => ({ ...o, [k]: Array.isArray(val[k]) ? val[k] : [val[k]] }), {});
};
function mergeBy(arr, mergeOn) {
const memo = [];
return arr.reduce((newArr, val) => {
const ix = memo.findIndex((v) => v === val[mergeOn]);
if (ix > -1) {
newArr[ix] = {
[mergeOn]: newArr[ix][mergeOn],
...mergeAllKeys(newArr, val, ix, mergeOn),
};
return newArr;
}
memo.push(val[mergeOn]);
return [
...newArr,
{
[mergeOn]: val[mergeOn],
...keysToArray(val, mergeOn),
},
];
}, []);
And later put it all together:
const array = [
{ title: 'test', data: [1], data2: ['data1', 'data2'] },
{ title: 'test', data: [2], data2: [1, 2] },
{ title: 'test1', data: [3], data2: [1, 2, 3] },
{ title: 'test1', data2: [1, 2, 3] },
{ title: 'test1', data2: 'string' },
{ title: 'test3', data2: 69 },
];
function mergeBy(arr, mergeOn) {
const memo = [];
return arr.reduce((newArr, val) => {
const ix = memo.findIndex((v) => v === val[mergeOn]);
if (ix > -1) {
newArr[ix] = {
[mergeOn]: newArr[ix][mergeOn],
...Object.keys(newArr[ix])
.filter((k) => k !== mergeOn)
.reduce((obj, k) => ({
...obj,
[k]: [
...newArr[ix][k],
...(Array.isArray(val[k]) ? val[k] : [val[k]]),
].filter((v) => v),
}), {}),
};
return newArr;
}
memo.push(val[mergeOn]);
return [
...newArr,
{
[mergeOn]: val[mergeOn],
...Object.keys(val)
.filter((k) => k !== mergeOn)
.reduce((o, k) => ({ ...o, [k]: Array.isArray(val[k]) ? val[k] : [val[k]] }), {}),
},
];
}, []);
}
const funkyMerge = mergeBy(array, 'title');
console.log('funkyMerge: ', funkyMerge);