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.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
Kamil Staszewski
  • 303
  • 7
  • 20
  • This should give you an idea: [Sum all properties in object](https://stackoverflow.com/q/30756835/218196). *"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. – Felix Kling Nov 07 '18 at 18:45
  • `const result = arr.filter(obj => Object.values(obj.expenses).every(expense => expense > 45))` – Pavlo Nov 07 '18 at 18:45
  • What **code** are you using to evaluate? – Neo Nov 07 '18 at 18:46
  • Change it to 25. How to iterate and get values of all expenses and filter that object? – Kamil Staszewski Nov 07 '18 at 18:47
  • 25 is still too high – Pavlo Nov 07 '18 at 18:48
  • 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 : / – Kamil Staszewski Nov 07 '18 at 18:50
  • Related: [Access / process (nested) objects, arrays or JSON](https://stackoverflow.com/questions/11922383/access-process-nested-objects-arrays-or-json) – Felix Kling Nov 07 '18 at 18:53
  • array.filter(object => Object.keys(object.expenses).reduce((total, key) => total + object.expenses[key], 0) > 35); – Donny Verduijn Nov 07 '18 at 19:11

5 Answers5

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);
sjahan
  • 5,720
  • 3
  • 19
  • 42
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
graciano
  • 310
  • 3
  • 10
  • 1
    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. – Felix Kling Nov 07 '18 at 19:15
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);
Alfredo A.
  • 1,697
  • 3
  • 30
  • 43
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

Tornike Shavishvili
  • 1,244
  • 4
  • 16
  • 35
-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; } } })

Velimir Tchatchevsky
  • 2,812
  • 1
  • 16
  • 21
  • 1
    Why should the OP try this? How does this solve their problem? – Felix Kling Nov 07 '18 at 18:46
  • 3
    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 – Felix Kling Nov 07 '18 at 18:49
  • 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! – Velimir Tchatchevsky Nov 07 '18 at 19:04
  • 1
    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. – Felix Kling Nov 07 '18 at 19:12
  • @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 – Velimir Tchatchevsky Nov 07 '18 at 19:18