2

I have an object array:

var example = [{a:1, b:2, c:3}, {a:4, b:5, c:6}, {a:7, b:8, c:9}]

I am trying to add all values that don't correspond with c.

  • I've managed to filter out a row, which wasn't what I was after, with console.log(test.filter(x => x.c > 3));

  • I've also tried a data query and chaining .ne("c") to it, but this didn't work.

I have managed to find the sum of an object array, but it doesn't omit the elements corresponding with "c". The code for that is:

var example = [{a:1, b:2, c:3}, {a:4, b:5, c:6}, {a:7, b:8, c:9}]
var sumobjects
sumobjects = example.map(y => Object.keys(y).reduce((x,z) => x + y[z], 0));
const reducer = (accumulator, currentValue) => accumulator + currentValue;
const sumexample = sumobjects.reduce(reducer)
console.log(sumexample);

My current code is looking like this:

var example = [{a:1, b:2, c:3}, {a:4, b:5, c:6}, {a:7, b:8, c:9}]
function filtration (arr) {

 var filteredsum = 0
 for (let i = 0; i < arr.length; i++) {
 for (let j = 0; j < arr[i].length; j++) {
 for(let k = 0; k < arr[i][j].length && arr[i][j] !== "c"; k++)
            filteredsum += arr[i][j]            
        }
    }   
 return(filteredsum);
}
console.log(filtration(example));

The answer should be one single number, being 27.

The code I currently have is outputting 0, so I figure that instead of omitting the property "c" from the sum, it's finding c and then omitting the entire object from the object array.

EDIT: The object array above is a simplified version of the object array I'm actually working with. The actual object array is not limited to the properties a, b and c. It has about 350 different properties. So code that adds a and b and c by actually stating a, b and c isn't going to be a good option for me.

Normajean
  • 1,075
  • 3
  • 11
  • 28

9 Answers9

3

You can do like this if you just want to exclude "c" property but include sum of values of all properties of objects of the array.

var example = [{a:1, b:2, c:3}, {a:4, b:5, c:6}, {a:7, b:8, c:9}];

let sum = 0; 
example.forEach(obj => {
    for (let property in obj) {
        if(property !== "c")
        sum += obj[property];
    }
})
  • This one will also work very well. I will still need the original object array for other calculations. So I have created a copy of var example and I have performed the code you have provided to the copy. – Normajean Aug 15 '19 at 06:20
  • @Normajean well the original example array is not affected by the forEach() method. So I do not think you need to create a different copy. Cheers. – JaxonFlexonWaxon Aug 15 '19 at 06:24
  • Thank you so much. I'm just learning javascript and have been trying to find the solution to this for about 5 days. Thanks again! – Normajean Aug 15 '19 at 06:29
  • Can you please upvote my answer if you found it useful. Thanks :) – JaxonFlexonWaxon Aug 15 '19 at 06:30
2

You can use the function below and pass the keys to omit as an array of string to the second parameter. The first parameter will be the list itself.

const sumWithout = (list, without) => {
  return list.reduce((acc, item) => {
    for (let [key, value] of Object.entries(item)) {
      if(!without.includes(key)){
        acc = Number(value) + acc;
      }
    }

    return acc;
  }, 0)
}

console.log(sumWithout(yourList, ['c', 'foo', '...' ]));
Morlo Mbakop
  • 3,518
  • 20
  • 21
2

You already have the code to add all properties.
Object.keys(y) get you all properties of the object, the reducer is using them with y[z] assuming z='a' it's like doing y.a: the solution is to filter unwanted properties before the reduce

The change is on this line:

var sumobjects = example.map(y => Object.keys(y).filter(k=>k!=='c').reduce((x,z) => x + y[z], 0));

Here the complete code:

var example = [{a:1, b:2, c:3}, {a:4, b:5, c:6}, {a:7, b:8, c:9}]
var sumobjects = example.map(y => Object.keys(y).filter(k=>k!=='c').reduce((x,z) => x + y[z], 0));
const reducer = (accumulator, currentValue) => accumulator + currentValue;
const sumexample = sumobjects.reduce(reducer)
console.log(sumexample);

If you want to exclude more than one property you can create an array with properties to avoid:
var exceptedProperties = ["c","d"];
The change is

var sumobjects = example.map(y => Object.keys(y).filter(k=>!exceptedProperties.some(p=>p===k)).reduce((x,z) => x + y[z], 0));

Complete code:

var example = [{a:1, b:2, c:3, d:4}, {a:4, b:5, c:6, d:7}, {a:7, b:8, c:9, d:10}]
var sumobjects = example.map(y => Object.keys(y).filter(k=>!exceptedProperties.some(p=>p===k)).reduce((x,z) => x + y[z], 0));
const reducer = (accumulator, currentValue) => accumulator + currentValue;
const sumexample = sumobjects.reduce(reducer)
console.log(sumexample);
Hedi
  • 306
  • 1
  • 11
  • 16
0
var example = [{a:1, b:2, c:3}, {a:4, b:5, c:6}, {a:7, b:8, c:9}]

var res = example.reduce((acc, curr) => {
    return acc = acc + curr.a + curr.b
}, 0)

You can reduce initial array that way and get desired result. It takes 0 as initial value and then add a and b properties of each element of the array

Puwka
  • 640
  • 5
  • 13
  • 1
    Thanks for your answer! I forgot to mention some crucial information in the question. The object array I have in my question is a very simplified version of what I have in reality. My actual object array has about 350 properties. So that return acc = curr.a + curr.b will need to be a mile long. That's why I'm really after some sort of filter or maybe I could create a new array that omits the undesired properties. – Normajean Aug 15 '19 at 05:59
  • Have a different answer [here](https://stackoverflow.com/a/57505519/9524336). Hope it helps – Puwka Aug 15 '19 at 06:16
0

If you want the sum of all "a" and "b" properties excluding "c", you can do it like this:

var example = [{a:1, b:2, c:3}, {a:4, b:5, c:6}, {a:7, b:8, c:9}];

let totalSum = 0;
example.forEach(obj => {
    let objSum = obj.a + obj.b;
    totalSum += objSum;
})
  • Thanks for your answer. I have added an edit to my question after your answer. I will have about 350 different properties, not just a, b and c. So I'm looking for a way to find their sum without having to state each property. – Normajean Aug 15 '19 at 06:11
  • @Normajean yes, I have added a different answer as well. Please have a look if that's what you need. – JaxonFlexonWaxon Aug 15 '19 at 06:11
0

Try

let example = [{a:1, b:2, c:3}, {a:4, b:5, c:6}, {a:7, b:8, c:9}];

let keys = Object.keys(example[0]).filter(k=> k!='c');
let sumObj = obj => keys.reduce((a,c)=> a + obj[c],0);

let totalSum = example.reduce((a,c)=> a + sumObj(c), 0);

console.log(totalSum);
Kamil Kiełczewski
  • 85,173
  • 29
  • 368
  • 345
  • Thanks for your answer. I have added an edit to my question after your answer. I will have about 350 different properties, not just a, b and c. So I'm looking for a way to find their sum without having to state each property. – Normajean Aug 15 '19 at 06:05
0

If you want to add every property of your objects except for some, you can filter them out by looping through the properties and checking whether they are the ones you are trying to avoid and act accordingly.

This code works regardless of the number of the properties and their names. You can expand it to filter out more properties if you like.

var example = [{a:1, b:2, c:3}, {a:4, b:5, c:6}, {a:7, b:8, c:9}]

const result = example.reduce((acc, cur) => {
  for (let el in cur) {
    acc += el !== "c" ? cur[el] : 0
  }
  return acc; 
}, 0)
console.log(result)
user1984
  • 5,990
  • 2
  • 13
  • 32
0

Hope this helps.

var example = [{a:1, b:2, c:3}, {a:4, b:5, c:6}, {a:7, b:8, c:9}];
var sum = 0;
for(var i = 0; i < example.length; i++){
    for(var j = 0; j < Object.keys(example[i]).length; j++){
        if(Object.keys(example[i])[j] != "c"){
        sum +=  parseInt(example[i][Object.keys(example[i])[j]]);
        }
    }
}

console.log(sum);
Ali Bacelonia
  • 1,213
  • 8
  • 8
0

Ok, I figured out, that your reallife object is huge. You can do that:

const result = example.map(item => {
    // first way (extract a, b)
    const {a, b} = item;
    // second way (omit c)
    const {c, ...rest} = item;
})

So what happens here. If its easier to you to extract properties from initial object then you go first way and return {a, b}. If its better to omit properties then you go second way and return rest

So Ill take second way and continue the code

const res = example.map(item => {
    const {c, ...rest} = item;
    return rest
}).reduce((acc, curr) => {
    Object.values(curr).forEach(value => acc = acc + value);
    return acc
}, 0);

If you choose first way - reducer will be the same, only map return will be different.

Puwka
  • 640
  • 5
  • 13