MountainMJ
MountainMJ

Reputation: 69

reducing a nested object in javascript

I have an object with the structure

"Office": {
    "California" : {
        "Contract1": {
            1: {Price: 1000, Count: 5},
            2: {Price: 2000, Count: 11},
            3: {Price: 3000, Count: 3},
            4: {Price: 2000, Count: 1},...
        },
        "Contract2": {
            1: {Price: 7000, Count: 6},
            2: {Price: 1000, Count: 4},
            3: {Price: 67000, Count: 6},
            4: {Price: 500, Count: 2},...
        },
        "Contract3": {
            1: {Price: 4000, Count: 4},
            2: {Price: 4000, Count: 1},
            3: {Price: 5000, Count: 12},
            4: {Price: 5000, Count: 2},...
        }
    },
    "North Carolina" : {
        "Contract1": {
            1: {Price: 7000, Count: 4},
            2: {Price: 7000, Count: 4},
            3: {Price: 7000, Count: 4},
            4: {Price: 7000, Count: 4},...
        },
        "Contract2": {
            1: {Price: 6000, Count: 4},
            2: {Price: 2000, Count: 10},
            3: {Price: 3000, Count: 3},
            4: {Price: 2000, Count: 3},...
        },
        "Contract3": {
            1: {Price: 4000, Count: 5},
            2: {Price: 2000, Count: 4},
            3: {Price: 4000, Count: 3},
            4: {Price: 2000, Count: 4},...
        },...
}

And I want to reduce it to this:

"Office": {
    "California" : {
        "Contract1": {
            1: {Price: 6000, Count: 19},
            2: {Price: 2000, Count: 1},...
        },
        "Contract2": {
            1: {Price: 75000, Count: 16},
            2: {Price: 500, Count: 2},...
        },
        "Contract3": {
            1: {Price: 13000, Count: 17},
            2: {Price: 5000, Count: 2},...
        }
    },
    "North Carolina" : {
        "Contract1": {
            1: {Price: 21000, Count: 12},
            2: {Price: 7, Count: 4},...
        },
        "Contract2": {
            1: {Price: 11000, Count: 17},
            2: {Price: 2000, Count: 3},...
        },
        "Contract3": {
            1: {Price: 10000, Count: 12},
            2: {Price: 2000, Count: 4},...
        },...
}

The number objects under each contract on the first structure represent the months past. In the second structure I want to sum up the properties of the first 3 number objects can call this 1. Then the second 3 would be 2. These are quarters.

I think I can do this with some sort of combination of map, reduce and filter but these are array functions and I have an object so I’m not sure how to do it. I need to do this for a non ES6 solution.

Any guidance would be really appreciated.

Upvotes: 0

Views: 93

Answers (2)

Ajai
Ajai

Reputation: 391

Based on count it will dynamically populate your required output

  const data = { "Office": {
"California" : {
    "Contract1": {
        1: {Price: 1000, Count: 5}, 2: {Price: 2000, Count: 11},
        3: {Price: 3000, Count: 3}, 4: {Price: 2000, Count: 1},
        5: {Price: 1000, Count: 5}, 6: {Price: 2000, Count: 11},
        7: {Price: 3000, Count: 3}, 8: {Price: 2000, Count: 1},
        9: {Price: 1000, Count: 5}, 10: {Price: 2000, Count: 11},
        11: {Price: 3000, Count: 3}, 12: {Price: 2000, Count: 1},
    },
    "Contract2": {
        1: {Price: 7000, Count: 6}, 2: {Price: 1000, Count: 4},
        3: {Price: 67000, Count: 6}, 4: {Price: 500, Count: 2},
        5: {Price: 7000, Count: 6}, 6: {Price: 1000, Count: 4},
        7: {Price: 67000, Count: 6}, 8: {Price: 500, Count: 2},
        9: {Price: 7000, Count: 6}, 10: {Price: 1000, Count: 4},
        11: {Price: 67000, Count: 6}, 12: {Price: 500, Count: 2},
    },
    "Contract3": {
        1: {Price: 4000, Count: 4}, 2: {Price: 4000, Count: 1},
        3: {Price: 5000, Count: 12}, 4: {Price: 5000, Count: 2},
        5: {Price: 4000, Count: 4}, 6: {Price: 4000, Count: 1},
        7: {Price: 5000, Count: 12}, 8: {Price: 5000, Count: 2},
        9: {Price: 4000, Count: 4}, 10: {Price: 4000, Count: 1},
        11: {Price: 5000, Count: 12}, 12: {Price: 5000, Count: 2},
    }
},
"North Carolina" : {
    "Contract1": {
        1: {Price: 7000, Count: 4}, 2: {Price: 7000, Count: 4},
        3: {Price: 7000, Count: 4}, 4: {Price: 7000, Count: 4},
        5: {Price: 7000, Count: 4}, 6: {Price: 7000, Count: 4},
        7: {Price: 7000, Count: 4}, 8: {Price: 7000, Count: 4},
        9: {Price: 7000, Count: 4}, 10: {Price: 7000, Count: 4},
        11: {Price: 7000, Count: 4}, 12: {Price: 7000, Count: 4},
    },
    "Contract2": {
        1: {Price: 6000, Count: 4}, 2: {Price: 2000, Count: 10},
        3: {Price: 3000, Count: 3}, 4: {Price: 2000, Count: 3},
        5: {Price: 6000, Count: 4}, 6: {Price: 2000, Count: 10},
        7: {Price: 3000, Count: 3}, 8: {Price: 2000, Count: 3},
        9: {Price: 6000, Count: 4}, 10: {Price: 2000, Count: 10},
        11: {Price: 3000, Count: 3}, 12: {Price: 2000, Count: 3},
    },
    "Contract3": {
        1: {Price: 4000, Count: 5}, 2: {Price: 2000, Count: 4},
        3: {Price: 4000, Count: 3}, 4: {Price: 2000, Count: 4},
        5: {Price: 4000, Count: 5}, 6: {Price: 2000, Count: 4},
        7: {Price: 4000, Count: 3}, 8: {Price: 2000, Count: 4},
        9: {Price: 4000, Count: 5}, 10: {Price: 2000, Count: 4},
        11: {Price: 4000, Count: 3}, 12: {Price: 2000, Count: 4},
    },
},
} }

let count = 3;
for(var parent in data['Office']){
  let child1 = data['Office'][parent];
  for(var con in child1){
    child1[con] = Object.keys(child1[con]).reduce((acc,ele,index)=>{
        let key = Math.trunc(index / count);
       return {...acc,...{[key+1]: (key+1 in acc) ? {Price:acc[key+1]['Price']+child1[con][ele]['Price'],Count:acc[key+1]['Count']+child1[con][ele]['Count']} : child1[con][ele]}}
    },{})
  }
}
console.log(data)

Upvotes: 1

richytong
richytong

Reputation: 2452

You can do it this way using a special map function I wrote that works on objects

const { pipe, fork, map, reduce, get } = rubico

const data = { "Office": {
    "California" : {
        "Contract1": {
            1: {Price: 1000, Count: 5}, 2: {Price: 2000, Count: 11},
            3: {Price: 3000, Count: 3}, 4: {Price: 2000, Count: 1},
            5: {Price: 1000, Count: 5}, 6: {Price: 2000, Count: 11},
            7: {Price: 3000, Count: 3}, 8: {Price: 2000, Count: 1},
            9: {Price: 1000, Count: 5}, 10: {Price: 2000, Count: 11},
            11: {Price: 3000, Count: 3}, 12: {Price: 2000, Count: 1},
        },
        "Contract2": {
            1: {Price: 7000, Count: 6}, 2: {Price: 1000, Count: 4},
            3: {Price: 67000, Count: 6}, 4: {Price: 500, Count: 2},
            5: {Price: 7000, Count: 6}, 6: {Price: 1000, Count: 4},
            7: {Price: 67000, Count: 6}, 8: {Price: 500, Count: 2},
            9: {Price: 7000, Count: 6}, 10: {Price: 1000, Count: 4},
            11: {Price: 67000, Count: 6}, 12: {Price: 500, Count: 2},
        },
        "Contract3": {
            1: {Price: 4000, Count: 4}, 2: {Price: 4000, Count: 1},
            3: {Price: 5000, Count: 12}, 4: {Price: 5000, Count: 2},
            5: {Price: 4000, Count: 4}, 6: {Price: 4000, Count: 1},
            7: {Price: 5000, Count: 12}, 8: {Price: 5000, Count: 2},
            9: {Price: 4000, Count: 4}, 10: {Price: 4000, Count: 1},
            11: {Price: 5000, Count: 12}, 12: {Price: 5000, Count: 2},
        }
    },
    "North Carolina" : {
        "Contract1": {
            1: {Price: 7000, Count: 4}, 2: {Price: 7000, Count: 4},
            3: {Price: 7000, Count: 4}, 4: {Price: 7000, Count: 4},
            5: {Price: 7000, Count: 4}, 6: {Price: 7000, Count: 4},
            7: {Price: 7000, Count: 4}, 8: {Price: 7000, Count: 4},
            9: {Price: 7000, Count: 4}, 10: {Price: 7000, Count: 4},
            11: {Price: 7000, Count: 4}, 12: {Price: 7000, Count: 4},
        },
        "Contract2": {
            1: {Price: 6000, Count: 4}, 2: {Price: 2000, Count: 10},
            3: {Price: 3000, Count: 3}, 4: {Price: 2000, Count: 3},
            5: {Price: 6000, Count: 4}, 6: {Price: 2000, Count: 10},
            7: {Price: 3000, Count: 3}, 8: {Price: 2000, Count: 3},
            9: {Price: 6000, Count: 4}, 10: {Price: 2000, Count: 10},
            11: {Price: 3000, Count: 3}, 12: {Price: 2000, Count: 3},
        },
        "Contract3": {
            1: {Price: 4000, Count: 5}, 2: {Price: 2000, Count: 4},
            3: {Price: 4000, Count: 3}, 4: {Price: 2000, Count: 4},
            5: {Price: 4000, Count: 5}, 6: {Price: 2000, Count: 4},
            7: {Price: 4000, Count: 3}, 8: {Price: 2000, Count: 4},
            9: {Price: 4000, Count: 5}, 10: {Price: 2000, Count: 4},
            11: {Price: 4000, Count: 3}, 12: {Price: 2000, Count: 4},
        },
    },
} }

const addContracts = (total, contract) => ({
  Price: total.Price + contract.Price,
  Count: total.Count + contract.Count,
})

const monthNumbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

const sumMonthsToQuarters = contract => {
  const quartered = {
    1: { Price: 0, Count: 0 },
    2: { Price: 0, Count: 0 },
    3: { Price: 0, Count: 0 },
    4: { Price: 0, Count: 0 },
  }
  for (const monthNum of monthNumbers) {
    const quarterNum = Math.ceil(monthNum / 3)
    quartered[quarterNum] = addContracts(quartered[quarterNum], contract[monthNum])
  }
  return quartered
}

const x = map(map(map(sumMonthsToQuarters)))(data)

console.log(JSON.stringify(x))
<script src="https://unpkg.com/rubico/index.js" crossorigin></script>

Upvotes: 0

Related Questions