Is there an elegant way (map ?) to transform my object from this
[
{id: 1, from: "1/1/2021", to: "1/2/2022"},
{id: 2, from: "1/3/2021", to: "1/4/2022"},
{id: 1, from: "1/5/2021", to: "1/6/2022"},
{id: 2, from: "1/6/2021", to: "1/7/2022"}
]
to:
{
1: [{from: "1/1/2021", to: "1/2/2022"}, {from: "1/5/2021", to: "1/6/2022"}],
2: [{from: "1/3/2021", to: "1/4/2022"}, {from: "1/6/2021", to: "1/7/2022"}]
}
Here is my code:
const res = [
{id: 1, from: "1/1/2021", to: "1/2/2022"},
{id: 2, from: "1/3/2021", to: "1/4/2022"},
{id: 1, from: "1/5/2021", to: "1/6/2022"},
{id: 2, from: "1/6/2021", to: "1/7/2022"}
]
let dict = {};
for(var i=0; i < res.length; i ) {
dict[res[i].id] = dict[res[i].id] || [];
dict[res[i].id].push({from:res[i].from, to:res[i].to});
}
console.log(dict);
CodePudding user response:
Array.reduce()
can solve your problem.
const res = [
{id: 1, from: "1/1/2021", to: "1/2/2022"},
{id: 2, from: "1/3/2021", to: "1/4/2022"},
{id: 1, from: "1/5/2021", to: "1/6/2022"},
{id: 2, from: "1/6/2021", to: "1/7/2022"}
];
var result = res.reduce(function(acc, {id, from, to}) {
(acc[id] = acc[id] || []).push({from, to});
return acc;
}, {});
console.log(result);
CodePudding user response:
You could create a groupBy()
function to group by any property, in this case id. We'd use Array.reduce()
to convert to the desired object.
Update: I've removed the property
itself, in this case id
from the resulting array groups.
let input = [ {id: 1, from: "1/1/2021", to: "1/2/2022"}, {id: 2, from: "1/3/2021", to: "1/4/2022"}, {id: 1, from: "1/5/2021", to: "1/6/2022"}, {id: 2, from: "1/6/2021", to: "1/7/2022"} ];
function groupBy(arr, property) {
return arr.reduce((acc, cur) => {
const { [property]: _, ...obj} = cur;
acc[cur[property]] = [...(acc[cur[property]] || []), obj];
return acc;
}, {})
}
console.log(groupBy(input, 'id'))
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>
You can also use lodash groupBy for this purpose, with a minimum of code:
let input = [ {id: 1, from: "1/1/2021", to: "1/2/2022"}, {id: 2, from: "1/3/2021", to: "1/4/2022"}, {id: 1, from: "1/5/2021", to: "1/6/2022"}, {id: 2, from: "1/6/2021", to: "1/7/2022"} ];
console.log('groupBy (lodash):', _.groupBy(input, 'id'));
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js" integrity="sha512-90vH1Z83AJY9DmlWa8WkjkV79yfS2n2Oxhsi2dZbIv0nC4E6m5AbH8Nh156kkM7JePmqD6tcZsfad1ueoaovww==" crossorigin="anonymous"></script>
And, finally you can reduce
using a Map
object as well:
let input = [ {id: 1, from: "1/1/2021", to: "1/2/2022"}, {id: 2, from: "1/3/2021", to: "1/4/2022"}, {id: 1, from: "1/5/2021", to: "1/6/2022"}, {id: 2, from: "1/6/2021", to: "1/7/2022"} ];
function groupBy(arr, property) {
return Object.fromEntries(arr.reduce((acc, cur) => {
return acc.set(cur[property], [...(acc.get(cur[property]) || []), cur]);
}, new Map()))
}
console.log(groupBy(input, 'id'))
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>