Home > OS >  How to add all numerical key-values in array of objects?
How to add all numerical key-values in array of objects?

Time:06-20

If you have an array of objects like so:

enter image description here

What's the best way to add all numerical values in each object so each one looks something like this:

{category: "A", total: 44}

So in the 0th item in the original array, 0 23 21 is 24, and is now represented by the new 'total' key.

Bearing in mind that the 'keys' with numerical values in the original array e.g. 'col2' are randomly generated (so another array like the original can have keys like 'somethingelse'.

I've attempted it with the following, but I believe it's not written correctly:

newArrayOfObjects.forEach(element => {
    Object.values(element).reduce((a, b) => a   b);
});

It may be good to know but the 'key' category always exists in each object and is fixed. All other key values are numerical and there'll always be more than one.

CodePudding user response:

Please check this.

const array = [
  {
    category: 'A',
    col1: 1,
    col2: 2,
    col3: 3,
  },
  {
    category: 'B',
    col1: 2,
    col2: 3,
    col3: 4,
  }
]

const result = array.map(obj => {
  const total = Object.values(obj).reduce((acc, value) => {
    if (typeof value === 'number') {
      return acc   value;
    }
    return acc;
  }, 0)
  return {
    category: obj.category,
    total
  }
})

console.log(result)

CodePudding user response:

You could use Array.map() along with Array.reduce() to sum the numeric values in the array.

We'd create a toNumber() function to get the numeric value of any property. If this is not a number, it will return 0 (keeping the total unchanged).

let arr = [
   { a: 0, category: "a", col2: 23, col3: 21 },
   { b: 0, category: "b", x: 100, y: 10, z: 1 },
   { j: 0, category: "x", foo: 25, bar: 50, meta: 'content' },
]

function toNumber(n) {
    return isNaN(n) ? 0: n;
}

function sumTotals(a) {
    return a.map(({ category, ...obj}) => {
        const total = Object.values(obj).reduce((total, value) => { 
            return total   toNumber(value); 
        }, 0);
        return { category, total };
    })
}

console.log('Totals:', sumTotals(arr))
.as-console-wrapper { max-height: 100% !important; }

CodePudding user response:

arr = [{x:1}, {x:3}]

arr.reduce((accumulator, current) => accumulator current.x, 0);

CodePudding user response:

var data = [
    { "category": "A", "col0": 5, "col1": 8, "some": "thing"},
    { "category": "B", "col1": 3, "col2": 5}
];

var res = data.map((it) => {
    const { category, ...rest } = it;
    return {
      ...it,
      total: Object.values(rest).reduce(
        (prev, curr) =>
          typeof curr === "number" ? prev   curr : prev, // add if the current value is numeric
          0
      )
    }
});

console.log(res);

/**
[
  {"category":"A","col0":5,"col1":8,"some":"tst","total":13}, 
  {"category":"B","col1":3,"col2":5,"total":8}
]
**/

CodePudding user response:

I think you are on the right way, you just need to do a bit more destructuring and type checking:

const aggregated = newArrayOfObjects.map((obj) =>
  Object.entries(obj).reduce(
    (newObj, [key, value]) => ({
      ...newObj,
      ...(typeof value === "number"
        ? { total: newObj.total   value }
        : { [key]: value }),
    }),
    { total: 0 }
  )
);

First, you map all objects to their representations as key-value-pairs. Then you iterate over these key-value pairs and keep all non-numerical values and their respective keys, while dropping key-value-pairs with a numerical value and replacing them by a property in which you aggregate the total value.

CodePudding user response:

Solution with reduce in O(n) complexity. (didn't add type checks for corner cases)

const result = newArrayOfObjects.reduce((prevResult, curItem) => {
  if (prevResult) {
    prevResult.push({
      category: curItem.category,
      total: curItem.col2   curItem.col3
    });
  }
  return prevResult;
}, []);
  • Related