Syed Ariff
Syed Ariff

Reputation: 732

How to append an object to an array based on the number of properties other than the specified properties?

For example , I have an array of objects like so :

[

{
      "waterfallData.PopulationName":"Population 1",
      "Deaths":-2333,
      "Births":8786,
      "open":0,
      "close":6453
   },
   {
      "waterfallData.PopulationName":"Population 2",
      "Deaths":-1000,
      "Births":5000,
      "open":0,
      "close":10453
   },
   {
      "waterfallData.PopulationName":"Population 3",
      "Deaths":-2000,
      "Births":500,
      "open":0,
      "close":8953
   }
]

I want to add two(does not have to be two,if there is a "Extra Births" then three) intermerdiate objects between each population like so

[

{
      "waterfallData.PopulationName":"Population 1",
      "Death":-2333,
      "Births":8786,
      "open":0,
      "close":6453
   },
   {
      "Deaths" : -1000,
       "open"   : 6453,
       "close"  : 5453
   },
   {
     "Births" : 5000,
      "open"   : 5453,
      "close   : 10453
   }
   {
      "waterfallData.PopulationName":"Population 2",
      "Deaths":-1000,
      "Births":5000,
      "open":0,
      "close":10453
   },
   {
      "Deaths" : -2000,
      "open"    : 10453,
      "close"   : 8453
   },
   {
      "Births" : 500,
      "open"    : 8453,
      "close"   : 8953
   }
   {
      "waterfallData.PopulationName":"Population 3",
      "Deaths":-2000,
      "Births":500,
      "open":0,
      "close":8953
   }
]

So as you can see I want to add objects based on the number of properties other than the waterfallData.PopulationName ,open and close properties. Then, I want to assign open and close properties on each object based on the next "Deaths" and "Births" values.

For example , Population 1 starts with 6453 then I add two objects with the 1st object taking the next "Deaths" value in Population 2 which is -1000 then I assign the open property to be from the previous close property of Population 1 and the close property to be calculated by adding the assigned open property to "Deaths"'s value. And same goes with the 2nd extra object where I assign the open property to be the close property of the previous object and the close property to be calculated by adding open with "Births"'s value.

How do I achieve this?

Upvotes: 2

Views: 86

Answers (2)

HymnZzy
HymnZzy

Reputation: 2925

Crude.. but works

var newArr = [];
$x = [{
    "waterfallData.PopulationName":"Population 1",
    "Deaths":-2333,
    "Births":8786,
    "open":0,
    "close":6453
},{
    "waterfallData.PopulationName":"Population 2",
    "Deaths":-1000,
    "Births":5000,
    "open":0,
    "close":10453
},{
    "waterfallData.PopulationName":"Population 3",
    "Deaths":-2000,
    "Births":500,
    "open":0,
    "close":8953
}];
$x.forEach((p,i)=>{
    var current = $x[i]
    newArr.push(current)
    try {
        var next = $x[i+1];
        var start = current.open;
        var end = current.close;
        var states = Object.keys(current).sort().filter((k)=>{return (['waterfallData.PopulationName','open','close'].indexOf(k) < 0)})
        for (var i=0;i<states.length;i++){
            var state = states[i]
            var tempObj = {}
            tempObj[states[i]] = next[states[i]]
            tempObj['open'] = end;
            end += next[states[i]];
            tempObj['close'] = end;
            newArr.push(tempObj)
        }
    } catch (e) {
        return false;
    }
})

The code will look for all properties other than waterfallData.Popu..,open,close and treats them as states. If you have 10 properties, there will be 7 states excluding the above 3. Then the open and close values of these states are then calculated from the next element and pushed to new array newArr.

Upvotes: 1

HMR
HMR

Reputation: 39250

I'll give it a try, you can specify what keys you need to be extra data but the original data must have values for those keys. It'll create the extra items in the order that the keys are provided:

const data = [{"waterfallData.PopulationName":"Population 1","Deaths":-2333,"Births":8786,"open":0,"close":6453},{"waterfallData.PopulationName":"Population 2","Deaths":-1000,"Births":5000,"open":0,"close":10453},{"waterfallData.PopulationName":"Population 3","Deaths":-2000,"Births":500,"open":0,"close":8953}];

const zip = (arr1, arr2) =>
  [...new Array(Math.max(arr1.length, arr2.length))]
    .map((_, i) => i)
    .map((i) => [arr1[i], arr2[i]]);
const extras = (keys) => ([current, next]) =>
  keys.map((key) => [key, next[key]]).reduce(
    ([result, lastClose], [key, nextValue]) => [
      result.concat({
        [key]: nextValue,
        open: lastClose,
        close: nextValue + lastClose,
      }),
      nextValue + lastClose,
    ],
    [[], current.close],
  )[0];
const withExtras = (keys) => ([current, next]) =>
  !next
    ? [current]
    : [current].concat(extras(keys)([current, next]));
console.log(
  zip(data, data.slice(1)) //having [[current,next],[current,next]...]
    .map(withExtras(['Deaths', 'Births']))
    .flatten(),
);

console.log(
  'diffenrent order different result',
  zip(data, data.slice(1))
    .map(withExtras(['Births', 'Deaths']))
    .flatten(),
);

Upvotes: 0

Related Questions