Hommer Smith
Hommer Smith

Reputation: 27852

Converting object format in Javascript

I have an input array of objects, which each object has the following format:

{
 titleID: string,
 titleName: string,
 1af23_red: number,
 45ua6_blue: number
}

What I know is that:

  1. In every object, there will be always the keys titleID and titleName and then I will have several keys that have the format number_string.

  2. The titleID and titleName values will be different among the different objects

  3. The rest of the keys (1af23_red, 45ua6_blue, etc) will be the same in all objects and they will all have the same format 'id_name' So, if the first object has 1af23_red and 45ua6_blue as keys, all the rest will also have just those keys.

The type of array that I want back has the following format:

{
  color: {
    id
    name
  },
  data: Array<
  {
    title: {
      id
      name
    },
    rating
  }
  >
}

So, example of input:

[ 
  { 
    titleId: 'a',
    titleName: 'atitle',
    '1af_red': 50
    'ba2_blue': 40
  },
  {
    titleId: 'b',
    titleName: 'btitle',
    '1af_red': 30
    'ba2_blue': null
  },
  {
    titleId: 'c',
    titleName: 'ctitle',
    '1af_red': null
    'ba2_blue': 10
  }
]

I would expect back:

[
  {
    color: {
      id: '1af',
      name: 'red'
    },
    data: [
      {
        title: {
          id: 'a',
          name: 'atitle',
        },
        rating: 50
      }, 
      {
        title: {
          id: 'b',
          name: 'btitle',
        },
        rating: 30
      },
      {
        title: {
          id: 'c',
          name: 'ctitle',
        },
        rating: null
      }
    ]
  },
  {
    color: {
      id: 'ba2',
      name: 'blue'
    },
    data: [
      {
        title: {
          id: 'a',
          name: 'atitle',
        },
        rating: 40
      }, 
      {
        title: {
          id: 'b',
          name: 'btitle',
        },
        rating: null
      },
      {
        title: {
          id: 'c',
          name: 'ctitle',
        },
        rating: 10
      }
    ]
  }
]

I have tried doing this conversion with map and reduce but I am stuck. Is there an easy way to accomplish this?

Upvotes: 1

Views: 339

Answers (2)

mooga
mooga

Reputation: 3297

You could try that

let elements = [ 
  { 
    titleId: 'a',
    titleName: 'atitle',
    '1af_red': 50,
    'ba2_blue': 40
  },
  {
    titleId: 'b',
    titleName: 'btitle',
    '1af_red': 30,
    'ba2_blue': null
  },
  {
    titleId: 'c',
    titleName: 'ctitle',
    '1af_red': null,
    'ba2_blue': 10
  }
]


let colors = []
let result = []

elements.forEach(currElem => {
  for(let attr in currElem){
    if(attr != "titleId" && attr != "titleName"){
      let color = attr.split("_")
      if(!colors.some(currColor => {return currColor == color[1]})){        
          colors.push({
            "id": color[0],
            "name": color[1]
            })
      }
    }
  }
})


colors.forEach(currColor => {
  result.push({
    "color" : currColor,
    "data": []
  })
  elements.forEach(currElement => {
     for(let attr in currElement){
      let color = []
        if(attr != "titleId" && attr != "titleName"){
            color = attr.split("_")
            if(color[1] == currColor.name){
                for(let i=0; i<result.length;i++){
                  if(result[i].color.name == color[1]){
                    result[i].data.push({
                        "title" : {
                          "id": currElement.titleId,
                          "name": currElement.titleName
                        },
                        "rating":currElement[attr]
                    })
                    break
                  }
                }
            }
        }
    }
  })
})



console.log(result)

Upvotes: 1

Arpit Agrawal
Arpit Agrawal

Reputation: 1180

Here you go.

Brief logic : Getting all the keys from the object at 0th index from data array. Looping over the keys, if key contains '_', pick the key, break it to form id and name pair, then map over all the data objects, get the score for that key and append it to the object with id and name values. Finally append this object to result array. Doing this for all the keys which contains '_'.

const data = [ 
  { 
    titleId: 'a',
    titleName: 'atitle',
    '1af_red': 50,
    'ba2_blue': 40
  },
  {
    titleId: 'b',
    titleName: 'btitle',
    '1af_red': 30,
    'ba2_blue': null
  },
  {
    titleId: 'c',
    titleName: 'ctitle',
    '1af_red': null,
    'ba2_blue': 10
  }
];
const keys = Object.keys(data[0]);
const result = []
keys.map(key=> {
  if(key.indexOf('_')!==-1){
    const item = {}
    const keyData = key.split('_')
    item.color = {
      id : keyData[0],
      name : keyData[1]
    }
    item.data = []
    data.map(obj => {
      const newObj = {}
      newObj.title = {
        id : obj.titleId,
          name : obj.titleName
      }
      newObj.rating = obj[key];
      item.data.push(newObj);
    });
  result.push(item);
  }
});
console.log(result);

Upvotes: 4

Related Questions