Reputation: 65
So i'm have an array of objects, i've created two dictonaries to map the names. I want to find all object with the same key and merge them. Also concatenate that values. Here is what i've done, but stucked:
const wordcloudData = {
'pretty cool': [3, 1, ['161', '329']],
'pretty damn': [2, 1, ['111', '131']],
'pretty nice': [1, 1, ['211', '499']],
'great': [4, 1, ['18', '19']],
};
const dict = {
'pretty cool': 1,
'pretty damn': 1,
'pretty nice': 1,
};
const dictNames = {
1: 'nice',
}
const formattedArray = _
.chain(wordcloudData)
.keys()
.map(item => {
const [weight, color, reviews] = wordcloudData[item];
return {
name: dictNames[dict[item]] || item,
weight: weight,
color: color,
reviews: reviews,
}
})
/* Here i'm getting that type of array:
[
{ name: 'nice', weight: 1, color: 1, reviews: [ '211', '499' ] },
{ name: 'nice', weight: 2, color: 1, reviews: [ '111', '131' ] },
{ name: 'nice', weight: 3, color: 1, reviews: [ '161', '329' ] },
{ name: 'great', weight: 4, color: 1, reviews: [ '18', '19' ] }
]
*/
.groupBy('name')
.map(_.spread(_.assign)) // Here i'm trying to get rid of objects with same key, but something goes wrong
.value();
I think i'm doing it wrong when removing duplicates? What should i do next?
To explain what I want, will show what array I want it to be:
Initial array of object:
{
'pretty cool': [3, 1, ['161', '329']],
'pretty damn': [2, 1, ['111', '131']],
'pretty nice': [1, 1, ['211', '499']],
'great': [4, 1, ['18', '19']],
};
Result array of objects:
{ name: 'nice', weight: 6, color: 1, reviews: [ '161', '329', '111', '131', '211', '499'] },
{ name: 'great', weight: 4, color: 1, reviews: [ '18', '19' ] }
Upvotes: 1
Views: 1673
Reputation: 13963
Here is a short solution using plain ES6, and separating the merge logic into its own function: https://jsbin.com/qevohugene/edit?js,console
const wordcloudData = {
'pretty cool': [3, 1, ['161', '329']],
'pretty damn': [2, 1, ['111', '131']],
'pretty nice': [1, 1, ['211', '499']],
'great': [4, 1, ['18', '19']],
};
const dict = {
'pretty cool': 1,
'pretty damn': 1,
'pretty nice': 1,
};
const dictNames = {
1: 'nice',
}
const mergeItems = (oldItem, newItem) => ({
name: newItem.name,
weight: newItem.weight + oldItem.weight,
color: newItem.color,
reviews: [...oldItem.reviews, ...newItem.reviews]
});
const formattedArray = Object.entries(wordcloudData)
.map(([key, [weight, color, reviews]]) => ({
name: dictNames[dict[key]] || key,
weight: weight,
color: color,
reviews: reviews,
}))
.reduce((accum, item) => {
return accum.some(x => x.name === item.name)
? accum.map(x => x.name === item.name ? mergeItems(x, item) : x)
: [...accum, item];
}, []);
console.log(formattedArray)
Hope that helps.
Upvotes: 1
Reputation: 191976
Use _.mergeWith()
and choose how to combine the values according to the key:
const wordcloudData = {
'pretty cool': [3, 1, ['161', '329']],
'pretty damn': [2, 1, ['111', '131']],
'pretty nice': [1, 1, ['211', '499']],
'great': [4, 1, ['18', '19']],
};
const dict = {
'pretty cool': 1,
'pretty damn': 1,
'pretty nice': 1,
};
const dictNames = {
1: 'nice',
}
const merger = _.partial(_.invoke, {
weight: _.add,
reviews: _.concat,
});
const formattedArray = _(wordcloudData)
.map(([weight, color, reviews], item) => ({
name: _.get(dictNames, dict[item], item),
weight,
color,
reviews
}))
.groupBy('name')
.map(v => _.mergeWith(...v, (o, s, k) => merger(k, o, s)))
.value();
console.log(formattedArray);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
Upvotes: 1
Reputation: 17190
Here you have one version without lodash
and using reduce():
const wordcloudData = {
'pretty cool': [3, 1, ['161', '329']],
'pretty damn': [2, 1, ['111', '131']],
'pretty nice': [1, 1, ['211', '499']],
'great': [4, 1, ['18', '19']],
};
const dict = {
'pretty cool': 1,
'pretty damn': 1,
'pretty nice': 1,
};
const dictNames = {
1: 'nice',
}
let merged = Object.keys(wordcloudData).reduce((res, curr) =>
{
let new_name = dictNames[dict[curr]] || curr;
let [weigth, color, review] = wordcloudData[curr];
let found = res.findIndex(x => x.name === new_name);
if (found >= 0)
{
res[found].weigth += weigth;
res[found].color = color;
res[found].review.push(...review);
}
else
{
res.push({
name: new_name,
weigth: weigth,
color: color,
review: review
});
}
return res;
}, []);
console.log(merged);
Upvotes: 1