Home > OS >  Javascript, how to transform this Array to Dictionary?
Javascript, how to transform this Array to Dictionary?

Time:09-30

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>

  • Related