0
\$\begingroup\$

I need to take sum of all the person's ages and heights.

Input Array:

[
  {
    "personId": 1,
    "ages": [
      1,
      4,
      5
    ],
    "heights": [
      1,
      1,
      2
    ]
  },
  {
    "personId": 2,
    "ages": [
      4,
      2,
      2
    ],
    "heights": [
      1,
      4,
      2
    ]
  },
  {
    "personId": 2,
    "ages": [
      2,
      1,
      1
    ],
    "heights": [
      12
    ]
  }
]

Desired Output:

[
  {
    "type": "ages",
    "values": 22
  },
  {
    "type": "heights",
    "values": 23
  }
]

My Solution (Which is working perfectly fine):

var agesTotal = 0;
var heightsTotal = 0;
var resultArr = [];

var sourceArr = [{personId: 1, ages: [1,4,5], heights: [1,1,2]}, {personId: 2, ages: [4,2,2], heights: [1,4,2]}, {personId: 2, ages: [2,1,1], heights: [12]}];

for(var i = 0; i < sourceArr.length; i++){

    if(sourceArr[i].ages){

        if(i == 0){

            resultArr.push({
                type: "ages",
                values: agesTotal
            });
        }

        for(var n = 0; n < resultArr.length; n++){

            if(resultArr[n].type == "ages"){

                resultArr[n].values += agesTotal + sourceArr[i].ages.reduce((partialSum, a) => parseFloat(partialSum) + parseFloat(a), 0)
            }
        }
    }

    if(sourceArr[i].heights){

        if(i == 0){

            resultArr.push({
                type: "heights",
                values: heightsTotal
            });
        }

        for(var n = 0; n < resultArr.length; n++){

            if(resultArr[n].type == "heights"){

                resultArr[n].values += heightsTotal + sourceArr[i].heights.reduce((partialSum, a) => parseFloat(partialSum) + parseFloat(a), 0)
            }
        }
    }
}

This above code of mine is producing the correct response, but it seems like so much processing and unoptimized.

What I need is the best & optimized possible solution for this operation

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

forEach and reduce remove all the effort of the loops, and patching up the output format.

You seem to deal with the possibility of ages or heights properties not existing in the input array, which adds some complexity to the reduce call. As written in the snippet, it deals with both.

IF the data always contains these, then you can simplify to:

ages += person.ages.reduce((a, b) => a + b)
heights += person.heights.reduce((a, b) => a + b)

If the array always exists but could be zero length, then you will need to provide an initial value for reduce:

ages += person.ages.reduce((a, b) => a + b, 0)
heights += person.heights.reduce((a, b) => a + b, 0)

const data = [{personId: 1, ages: [1,4,5], heights: [1,1,2]}, {personId: 2, ages: [4,2,2], heights: [1,4,2]}, {personId: 2, ages: [2,1,1], heights: [12]}, {personId: 3, heights: []}];

function sumAgesAndHeights(data) {
    let ages = 0;
    let heights = 0;
    data.forEach(person => {
        ages += person.ages?.reduce((a, b) => a + b, 0) ?? 0;
        heights += person.heights?.reduce((a, b) => a + b, 0) ?? 0;
    })
    return [
        {
            "types": "ages",
            "values": ages
        },
        {
            "types": "heights",
            "values": heights
        }
    ];
}

console.log(sumAgesAndHeights(data))

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.