Home > OS >  Transforming structure of JSON and mapping to new object
Transforming structure of JSON and mapping to new object

Time:08-08

I'm quite new to Javascript, and not sure if I'm defining the question correctly. I have a JSON in one format/layout and trying to transform it to another structure.

What I currently have is:

const have = 
[{"year":"2005","type":"A","y1":"8","y2":"5"},
{"year":"2006","type":"A","y1":"11","y2":"4"},
{"year":"2007","type":"A","y1":"2","y2":"5"},
{"year":"2008","type":"A","y1":"6","y2":"6"},
{"year":"2009","type":"A","y1":"9","y2":"2"},
{"year":"2005","type":"B","y1":"16","y2":"1"},
{"year":"2006","type":"B","y1":"8","y2":"9"},
{"year":"2007","type":"B","y1":"9","y2":"0"},
{"year":"2008","type":"B","y1":"3","y2":"8"},
{"year":"2009","type":"B","y1":"1","y2":"5"}];

I would like the new structure to appear like this:

const want = 
[{"type": "A",
"x":[2005,2006,2007,2008,2009],
"y1":[8,11,2,6,9],
"y2":[5,4,5,6,2]},
{"type": "B",
"x":[2005,2006,2007,2008,2009],
"y1":[16,8,9,3,1],
"y2":[1,9,0,8,5]}];

I'm not sure if this is a matter of looping through the items, or if there is a map function that can help transform it.

CodePudding user response:

This is a grouping problem so reduce can be used to solve this. I'm grouping by type and then taking the values array using Object.values.
acc[type]??={type,x:[],y1:[],y2:[]} is like an initializer if it is not already available. this can also be written as acc[type] = acc[type] || {type,x:[],y1:[],y2:[]}

const have = 
[{"year":"2005","type":"A","y1":"8","y2":"5"},
{"year":"2006","type":"A","y1":"11","y2":"4"},
{"year":"2007","type":"A","y1":"2","y2":"5"},
{"year":"2008","type":"A","y1":"6","y2":"6"},
{"year":"2009","type":"A","y1":"9","y2":"2"},
{"year":"2005","type":"B","y1":"16","y2":"1"},
{"year":"2006","type":"B","y1":"8","y2":"9"},
{"year":"2007","type":"B","y1":"9","y2":"0"},
{"year":"2008","type":"B","y1":"3","y2":"8"},
{"year":"2009","type":"B","y1":"1","y2":"5"}];

const want = Object.values(have.reduce((acc,{year,type,y1,y2}) => {
  acc[type]??={type,x:[],y1:[],y2:[]}
  acc[type].x.push(parseInt(year))
  acc[type].y1.push(parseInt(y1))
  acc[type].y2.push(parseInt(y2))
  return acc
},{}))

console.log(want)

CodePudding user response:

Here's how I would do it:

The first operation is to create an empty object. Then looping through each item in the have array create a subobject of each "type" to store the values - but only if this has not been already created by a previous pass. Once created we can append each value to the proper bucket.

At the end of this loop we convert the object into the array format that you were looking for via a Array.map() operation on the keys of the object we used to store the sorted data.

const have = 
[{"year":"2005","type":"A","y1":"8","y2":"5"},
{"year":"2006","type":"A","y1":"11","y2":"4"},
{"year":"2007","type":"A","y1":"2","y2":"5"},
{"year":"2008","type":"A","y1":"6","y2":"6"},
{"year":"2009","type":"A","y1":"9","y2":"2"},
{"year":"2005","type":"B","y1":"16","y2":"1"},
{"year":"2006","type":"B","y1":"8","y2":"9"},
{"year":"2007","type":"B","y1":"9","y2":"0"},
{"year":"2008","type":"B","y1":"3","y2":"8"},
{"year":"2009","type":"B","y1":"1","y2":"5"}];

const types = {};

function createNewType(){
  return {
    x: [],
    y1: [],
    y2: []
  }
}

have.forEach(item => {
  const { type, year, y1, y2} = item;
  if(!types.hasOwnProperty(type)){
    types[type] = createNewType();
  }
  types[type].x.push(year);
  types[type].y1.push(y1);  
  types[type].y2.push(y2);
});

const want = Object.keys(types).map(key => {
  const value = types[key];
  return {
    type: key,
    ...value
  }
});

console.log(want)

CodePudding user response:

You need to iterate by the itens of the old array and build a new item every time you see a different type field. Something in the lines of (beware, pseudo code bellow)

    let want = []
    let type = null
    let cur = null
    for(let item of have) {
      if(item.type !== type) {
        type = item.type
        cur = { type, x: [], y1: [], y2: [] }
        want.push(cur)
      }
      cur.x.push(item.year)
      cur.y1.push(item.y1)
      cur.y2.push(item.y2)
    }

Notice that you will have to convert each item to the correct format while you push them into their respective arrays (i.e. convert String to Number)

  • Related