1

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?

mplungjan
  • 169,008
  • 28
  • 173
  • 236
Hommer Smith
  • 26,772
  • 56
  • 167
  • 296

2 Answers2

4

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);
Arpit Agrawal
  • 1,180
  • 1
  • 10
  • 21
  • Here is another challenge for you: https://stackoverflow.com/questions/54634114/plain-js-cascading-selects-of-unknown-depth – mplungjan Feb 15 '19 at 13:02
  • @mplungjan i think its not tough but require lot code to actually build a solution. What i would do is, get list of keys in `selObject["-- Select Item --"]` and put it in dropdown_1. user updated this d_1, get list of keys from `selObject.dropdown_1` and show dropdown_2. when user selects d_2, show dropdown_3 with list of keys from `selObject.d_1.d_2.` Keep doing this till list of keys is not empty.Catch is always store the current object data in a single variable, so recursively you can drill down to any level. Example `data=selObject` then `data= data.d_1` then do` `data=data.d_2` – Arpit Agrawal Feb 15 '19 at 13:39
1

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)
mooga
  • 3,136
  • 4
  • 23
  • 38