Rebuilding/Parsing plain JavaScript object

Viewed 62

Let's say I have an object containing objects that have 30 key-value pairs each:

const data = {
        "foo": {
            "3/16/21": 'buzz',
            "3/17/21": 'fizz',
            ...
            "4/13/21": 'lorem',
            "4/14/21": 'ipsum'
        },
        "bar": {
            "3/16/21": 'sit',
            "3/17/21": 'amet',
            ...
            "4/13/21": 'dummy',
            "4/14/21": 'text'
        },
    };

My goal is to rebuild this object into something like this:

myData = [
        {date: "3/16/21", foo: 'buzz', bar : 'sit'}
        {date: "3/17/21", foo: 'fizz', bar : 'amet'} ,
            ...
        {date: "4/13/21", foo: 'lorem', bar : 'dummy'}
        {date: "4/14/21", foo: 'ipsum', bar : 'text'}
         ];

The function below works like charm but I feel like there is a 10x better way to do it. I would love to see your suggestions on how I could improve it.

const processAPIdata = (data) => {
        if (data) {
            var myData = [];

            for (var key in data) {
                if (!data.hasOwnProperty(key)) continue;
                var obj = data[key];
                for (var prop in obj) {

                    if (!obj.hasOwnProperty(prop)) continue;
                    if (myData.length < 30) {
                        myData.push({ date: prop });
                    }
                    let pos = myData.map(function (e) { return e.date; }).indexOf(prop);
                    myData[pos][key] = obj[prop];
                }
            }
        }
        return myData;
    };
3 Answers

I'd group into an object indexed by date. When iterating, create the object for that date if it doesn't exist yet, with { date } (where date is the inner property being iterated over), and assign a new property from the outer key (for the new key) and the inner value (for the new value):

const data = {
    "foo": {
        "3/16/21": 'buzz',
        "3/17/21": 'fizz',
        "4/13/21": 'lorem',
        "4/14/21": 'ipsum'
    },
    "bar": {
        "3/16/21": 'sit',
        "3/17/21": 'amet',
        "4/13/21": 'dummy',
        "4/14/21": 'text'
    },
};

const newDataByDate = {};
for (const [key, obj] of Object.entries(data)) {
  for (const [date, val] of Object.entries(obj)) {
    newDataByDate[date] ??= { date };
    newDataByDate[date][key] = val;
  }
}
console.log(Object.values(newDataByDate));

We can achieve this using Object.entries, Array.reduce & Object.values like below

const data = {"foo":{"3/16/21":'buzz',"3/17/21":'fizz',"4/13/21":'lorem',"4/14/21":'ipsum'},"bar":{"3/16/21":'sit',"3/17/21":'amet',"4/13/21":'dummy',"4/14/21":'text'}};

const formatData = (data) => {
//Convert the object to array of arrays with value at first index being the keys and value at second index being values
  const result = Object.entries(data).reduce((acc, [key, val]) => {
  //Since we have object as value, we need to again convert to array of arrays in order to get the date and the corresponding value
    Object.entries(val).forEach(([date, innerVal]) => {
    //update the accumulator with new key-value
      acc[date] = {
        ...(acc[date] || {date}),
        [key]: innerVal
      }
    })
    return acc;
  }, {});

//Return the values of the accumulator
  return Object.values(result);
}

console.log(formatData(data));
.as-console-wrapper {
  max-height: 100% !important;
}

You can complete by doing this simple way.

const data = {"foo":{"3/16/21":'buzz',"3/17/21":'fizz',"4/13/21":'lorem',"4/14/21":'ipsum'},"bar":{"3/16/21":'sit',"3/17/21":'amet',"4/13/21":'dummy',"4/14/21":'text'},};

const result = Object.entries(data).reduce((acc, [key, values]) => {
  for(const [date, v] of Object.entries(values)){
    acc[date] = acc[date] || {date}
    acc[date][[key]] = v;
  }
  
  return acc;
}, {});
console.log(Object.values(result));

Related