anarchy
anarchy

Reputation: 551

Create nested json from flattened JSON in javascript

Started with javascript recently. I have a flattened json which looks like :

[
{"timestamp":"2019-01-01T00:00:00.000Z","MarketShare":89905.0,"Territory":"PHILADELPHIA PA"},
{"timestamp":"2019-01-01T00:00:00.000Z","MarketShare":82991.0,"Territory":"SEATTLE WA"},
{"timestamp":"2019-02-01T00:00:00.000Z","MarketShare":73662.0,"Territory":"PHILADELPHIA PA"},
{"timestamp":"2019-02-01T00:00:00.000Z","MarketShare":67059.0,"Territory":"SEATTLE WA"},
{"timestamp":"2019-03-01T00:00:00.000Z","MarketShare":72898.0,"Territory":"PHILADELPHIA PA"},
{"timestamp":"2019-03-01T00:00:00.000Z","MarketShare":68013.0,"Territory":"SEATTLE WA"},
{"timestamp":"2019-04-01T00:00:00.000Z","MarketShare":74607.0,"Territory":"PHILADELPHIA PA"},
{"timestamp":"2019-04-01T00:00:00.000Z","MarketShare":66769.0,"Territory":"SEATTLE WA"},
{"timestamp":"2019-05-01T00:00:00.000Z","MarketShare":93932.0,"Territory":"PHILADELPHIA PA"},
{"timestamp":"2019-05-01T00:00:00.000Z","MarketShare":86514.0,"Territory":"SEATTLE WA"}
]

Basically, for a given timestamp, I want to collect MarketShare and Territory under the result key.
The expected output is :

    [
   {
      "timestamp":"2019-01-01T00:00:00.000Z",
      "result":[
         {
            "MarketShare":89905.0,
            "Territory":"PHILADELPHIA PA"
         },
         {
            "MarketShare":82991.0,
            "Territory":"SEATTLE WA"
         },

      ]
   },
   {
      "timestamp":"2019-02-01T00:00:00.000Z",
      "result":[
         {
            "MarketShare":73662.0,
            "Territory":"PHILADELPHIA PA"
         },
         {
            "MarketShare":67059.0,
            "Territory":"SEATTLE WA"
         }
      ]
   },
   {
      "timestamp":"2019-03-01T00:00:00.000Z",
      "result":[
         {
            "MarketShare":72898.0,
            "Territory":"PHILADELPHIA PA"
         },
         {
            "MarketShare":68013.0,
            "Territory":"SEATTLE WA"
         }
      ]
   },
   {
      "timestamp":"2019-04-01T00:00:00.000Z",
      "result":[
         {
            "MarketShare":74607.0,
            "Territory":"PHILADELPHIA PA"
         },
         {
            "MarketShare":66769.0,
            "Territory":"SEATTLE WA"
         }
      ]
   },
   {
      "timestamp":"2019-05-01T00:00:00.000Z",
      "result":[
         {
            "MarketShare":93932.0,
            "Territory":"PHILADELPHIA PA"
         },
         {
            "MarketShare":86514.0,
            "Territory":"SEATTLE WA"
         }
      ]
   }
]

I am trying to create a generic utility that puts any number of key value pair under a given timestamp. The progress made so far:

topNFormat=[]
for(var i = 0; i < firstResult.length; i++) {
    //res = [firstResult[i]["Territory"]
    topNFormat[timestamp] = firstResult[i][timestamp] || {};
    topNFormat[result] = firstResult[i][result] || [];
    topNFormat[result].push(firstResult[i]);
    //return collection;
}

Upvotes: 0

Views: 81

Answers (2)

Andy
Andy

Reputation: 525

Here is the simple solution by using built-in reduce function:

[].reduce((memo, item) => {
    memo[item.timestamp] = memo[item.timestamp] ||
                          { timestamp: item.timestamp, result: [] };
    memo[item.timestamp].result.push({
       MarketShare: item.MarketShare,
       Territory: item.Territory 
    });
    return memo;
 }, {});

Update 2 (more generic)

[].reduce((memo, item) => {
    memo[item.timestamp] = memo[item.timestamp] ||
                          { timestamp: item.timestamp, result: [] };
    // push whole item into result list
    memo[item.timestamp].result.push({ ...item });
    return memo;
 }, {});

Upvotes: 1

Umair Sarfraz
Umair Sarfraz

Reputation: 5953

Here's a general purpose function transform that would group items dynamically:

const input = [{
    "timestamp": "2019-01-01T00:00:00.000Z",
    "MarketShare": 89905.0,
    "Territory": "PHILADELPHIA PA"
  },
  {
    "timestamp": "2019-01-01T00:00:00.000Z",
    "MarketShare": 82991.0,
    "Territory": "SEATTLE WA"
  },
  {
    "timestamp": "2019-02-01T00:00:00.000Z",
    "MarketShare": 73662.0,
    "Territory": "PHILADELPHIA PA"
  },
  {
    "timestamp": "2019-02-01T00:00:00.000Z",
    "MarketShare": 67059.0,
    "Territory": "SEATTLE WA"
  },
  {
    "timestamp": "2019-03-01T00:00:00.000Z",
    "MarketShare": 72898.0,
    "Territory": "PHILADELPHIA PA"
  },
  {
    "timestamp": "2019-03-01T00:00:00.000Z",
    "MarketShare": 68013.0,
    "Territory": "SEATTLE WA"
  },
  {
    "timestamp": "2019-04-01T00:00:00.000Z",
    "MarketShare": 74607.0,
    "Territory": "PHILADELPHIA PA"
  },
  {
    "timestamp": "2019-04-01T00:00:00.000Z",
    "MarketShare": 66769.0,
    "Territory": "SEATTLE WA"
  },
  {
    "timestamp": "2019-05-01T00:00:00.000Z",
    "MarketShare": 93932.0,
    "Territory": "PHILADELPHIA PA"
  },
  {
    "timestamp": "2019-05-01T00:00:00.000Z",
    "MarketShare": 86514.0,
    "Territory": "SEATTLE WA"
  }
];

const transform = (array, groupBy, groupUnder) => array.reduce((acc, object) => {
  if (groupBy in object) {
    if (object[groupBy] in acc) {
      acc[object[groupBy]][groupUnder] = [
        ...acc[object[groupBy]][groupUnder],
        ...[Object.keys(object).filter((key) => key !== groupBy).reduce((acc, key) => {
          acc[key] = object[key];

          return acc;
        }, {})]
      ]
    } else {
      acc[object[groupBy]] = {
        [groupUnder]: [Object.keys(object).filter((key) => key !== groupBy).reduce((acc, key) => {
          acc[key] = object[key];

          return acc;
        }, {})]
      }
    }
  }

  return acc;
}, {});

const groupBy = 'timestamp';
const groupUnder = 'result';

const transformedResult = transform(input, groupBy, groupUnder);

console.log(transformedResult);

console.log('-'.repeat(100));

console.log(Object.keys(transformedResult).map((key) => Object.assign({}, transformedResult[key], {
  [groupBy]: key
})));

Upvotes: 3

Related Questions