8

I have a problem with filtering an array with nested objects.

[{
    "firstName": "Kevin",
    "lastName": "Smith",
    "expenses": {
      "drink1": 25,
      "drink2": 20
    }
  },
  {
    "firstName": "John",
    "lastName": "Rambo",
    "expenses": {
      "coffe": 10,
      "cake": 20
    }
  }
]

I want to get the objects where the sum of all expenses is > 35. How to get inside expenses? Or maybe filter is not a proper way here.

8
  • This should give you an idea: Sum all properties in object. "Or maybe filter is not a proper way here." It's absolutely the right way. You just need to sum the values of expenses inside the filter callback. Commented Nov 7, 2018 at 18:45
  • const result = arr.filter(obj => Object.values(obj.expenses).every(expense => expense > 45)) Commented Nov 7, 2018 at 18:45
  • What code are you using to evaluate? Commented Nov 7, 2018 at 18:46
  • Change it to 25. How to iterate and get values of all expenses and filter that object? Commented Nov 7, 2018 at 18:47
  • 1
    I want to receive objects where the sum of values inside a expenses object is above 25. That the example. Your code doesn't work : / Commented Nov 7, 2018 at 18:50

5 Answers 5

10

Just filter it, with a condition using reduce to sum the expenses! Pretty straight forward :)

const input = [{
    "firstName": "Kevin",
    "lastName": "Smith",
    "expenses": {
      "drink1": 26,
      "drink2": 20
    }
  },
  {
    "firstName": "John",
    "lastName": "Rambo",
    "expenses": {
      "coffe": 10,
      "cake": 20
    }
  }
];

const output = input.filter(user => Object.values(user.expenses).reduce((acc, expense) => acc + expense) > 45);
console.log(output);

Sign up to request clarification or add additional context in comments.

3 Comments

We have a winner. Thank you!
Glad it helps ;) Don't forget to mark the answer as accepted so that it can help the rest of the community :)
I didn't knew about Object.values. Nice!
1

I'm assuming that you need to keep you array of users the way it is, but with the expenses filtered.

(I assumed wrong as pointed in the comment, keeping this answer just in case someone sees any value on it)

Probably this can be optmized or simplified, but here it goes:

arr.reduce((acc, user) => [...acc,
  Object.keys(user).reduce((userResult, key) => {
    if (key === 'expenses') {
      return {
         ...userResult,
        expenses: Object.entries(elem.expenses)
          .filter(([product, value]) => value > 35)
          // now "reversing" the object.entries
          .reduce((acc, [product, value]) => ({ [product]: value }), {})
      }
    }
    return {
      ...userResult,
      [key]: elem[key]
    }
  }, user) // starts with the user
], []) //starts with empty array

1 Comment

The OP want's to get all user objects whose sum of the expenses is larger than N. They don't want to filter out expenses.
0

You can try something like this

var data = [{
    "firstName": "Kevin",
    "lastName": "Smith",
    "expenses": {
      "drink1": 25,
      "drink2": 20
    }
  },
  {
    "firstName": "John",
    "lastName": "Rambo",
    "expenses": {
      "coffe": 10,
      "cake": 20
    }
  }
]

var filtered = data.filter(c => Object.keys(c.expenses)
                                .reduce(function(p, e) {
                                     return p + c.expenses[e]
                                       }, 0) >= 35
                           );

console.log(filtered);

Comments

0

You can access object at index i inside array arr with expression arr[i] What you need to do is to loop over your array. Inside your loop you access each object with expression i have mentioned: arr[i] and then on this object you can access expenses following way arr[i].expenses after this - if i am understanding correctly you sum contents of your arr[i].expenses object and select those objects which satisfy your condition. Please, See code below:

var expensesAbove35Arr = [];

var yourArray = [
        {
            "firstName": "Kevin",
            "lastName": "Smith",
            "expenses": {
                          "drink1": 26,
                           "drink2": 20
                        }
        },
        {
            "firstName": "John",
            "lastName": "Rambo",
            "expenses": {
                          "coffe": 10,
                           "cake": 20
                        }
        }
];

for(var i=0; i<yourArray.length; i++){
    if(yourArray[i].expenses.coffe + yourArray[i].expenses.cake > 35 ){
        expensesAbove35Arr.push(yourArray[i]);
    }
}

You have got your result inside array expensesAbove35Arr

Comments

-3

A possible solution might be:

arr.filter(function(v){ for(expense in v.expenses){ if(v.expenses[expense] > 10){ return true; }else{ return false; } } })

5 Comments

Why should the OP try this? How does this solve their problem?
So, if they are asking how to sum all property values, you are showing how to access a single property, because actually answering the question would be a too much? O_o
No they are trying to solve a problem, and they have tried something which didn't work (not that OP did). We help them with the specific problem that's in their code, not writing the solution to their problem from scratch!
I agree. But if you only say "try this" then that seems to imply that you are providing a full fledged solution to their problem. But you are not. Your code example is somewhat related but doesn't produce the result they want. So at the very least you should explain what you are doing and how this helps them get to solving their problem.
@FelixKling Maybe the wording is ambiguous, what I meant was exactly the opposite - to point out how to access the array and leave the other part of the question to OP

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.