Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find Object inside Array inside another Array

let bigArray = [
{
    Name: 'Trump',
    children: [
                 {Name: 'TrumpChild1', City: 'city1'}, 
                 {Name: 'TrumpChild2', City: 'city2'}
    ]
},
{
    Name: 'Barack Obama',
    children: [
                 {Name: 'Barack Obama Child1', City: 'city3'}, 
                 {Name: 'Barack Obama Child2', City: 'city4'}
    ]
},
{
    Name: 'Clinton',
    children: [
                 {Name: 'Clinton Child 1', City: 'city5'}, 
                 {Name: 'Clinton Child2', City: 'city6'}
    ]
},

]

I want find a object from array inside another array

bigArray.find(b => b.children.find(c=>c.City === 'city1'))

the code above return the ARRAY father

bigArray.forEach(b => b.children.find(c=>c.City === 'city1'))

and this return undefined

What's the best way to return the desired object ?

like image 726
felipe muner Avatar asked Jan 28 '23 02:01

felipe muner


2 Answers

You can first flaten this array to an array of inner objects and then use filter() or find().

let bigArray = [
  {
      Name: 'Trump',
      children: [
                   {Name: 'TrumpChild1', City: 'city1'}, 
                   {Name: 'TrumpChild2', City: 'city2'}
      ]
  },
  {
      Name: 'Barack Obama',
      children: [
                   {Name: 'Barack Obama Child1', City: 'city3'}, 
                   {Name: 'Barack Obama Child2', City: 'city4'}
      ]
  },
  {
      Name: 'Clinton',
      children: [
                   {Name: 'Clinton Child 1', City: 'city5'}, 
                   {Name: 'Clinton Child2', City: 'city6'}
      ]
  }
];

let all = bigArray.reduce((prev, next) => prev.concat(next.children), []);
let result = all.find(obj => obj.City === 'city1');
console.log(result);

// if there can be multiple matches then use filter
let results = all.filter(obj => obj.City === 'city1');
console.log(results);
like image 59
Zohaib Ijaz Avatar answered Jan 31 '23 08:01

Zohaib Ijaz


Children could be born in the same city and so find() is not particularly well-suited for this problem as it only returns the first result its looking for. In this case filter() is the function we need.

Below, we call filter inside of reduce(). This is different from the other answer as it does not iterate thru your input data more than once. The other answer will first create an entire array of children, then in a second iteration, select the ones that match your city query.

Alternatively, this answer iterates thru each president once and adds any matching children to the result along the way.

const findByCity = (city, data = {}) =>
  data .reduce
    ( (result, { children = [] }) =>
        result .concat (children .filter (c => c.city === city))
    , []
    )

In your input data, each child has a unique city, so it doesn't yield a good demonstration. I've added some more children born in city5 so we can see an answer that includes multiple children

const data =
  [ { name: 'Trump'
    , children:
        [ { name: 'Trump Child 1', city: 'city1' }
        , { name: 'Trump Child 2', city: 'city2' }
        ]
    }
  , { name: 'Barack Obama'
    , children:
        [ { name: 'Barack Obama Child 1', city: 'city3' }
        , { name: 'Barack Obama Child 2', city: 'city4' }
        ]
    }
  , { name: 'Clinton'
    , children:
        [ { name: 'Clinton Child 1', city: 'city5' }
        , { name: 'Clinton Child 2', city: 'city6' }
        ]
    }
  , { name: 'Bush'
    , children:
        [ { name: 'Bush Child 1', city: 'city5' }
        , { name: 'Bush Child 2', city: 'city5' }
        ]
    }
  ]

console .log (findByCity ('city1', data))
// [ { name: 'Trump Child 1', city: 'city1' } ]

console .log (findByCity ('city5', data))
// [ { name: 'Clinton Child 1', city: 'city5' }
// , { name: 'Bush Child 1', city: 'city5' }
// , { name: 'Bush Child 2', city: 'city5' }
// ]

Another answer provided here would break if your data contained a children-less president. findByCity does not suffer from this problem

const data =
  [ // ...
  , { name: 'Bush'
    , children:
        [ { name: 'Bush Child 1', city: 'city5' }
        , { name: 'Bush Child 2', city: 'city5' }
        ]
    }

  // watch out for child-less presidents!
  , { name: 'Polk' }
  ]

Expand the program below to run it in your browser

const findByCity = (city, data = {}) =>
  data .reduce
    ( (result, { children = [] }) =>
        result .concat (children .filter (c => c.city === city))
    , []
    )

const data =
  [ { name: 'Trump'
    , children:
        [ { name: 'Trump Child 1', city: 'city1' }
        , { name: 'Trump Child 2', city: 'city2' }
        ]
    }
  , { name: 'Barack Obama'
    , children:
        [ { name: 'Barack Obama Child 1', city: 'city3' }
        , { name: 'Barack Obama Child 2', city: 'city4' }
        ]
    }
  , { name: 'Clinton'
    , children:
        [ { name: 'Clinton Child 1', city: 'city5' }
        , { name: 'Clinton Child 2', city: 'city6' }
        ]
    }
  , { name: 'Bush'
    , children:
        [ { name: 'Bush Child 1', city: 'city5' }
        , { name: 'Bush Child 2', city: 'city5' }
        ]
    }
  , { name: 'Polk' }
  ]

console .log (findByCity ('city1', data))
// [ { name: 'Trump Child 1', city: 'city1' } ]
    
console .log (findByCity ('city5', data))
// [ { name: 'Clinton Child 1', city: 'city5' }
// , { name: 'Bush Child 1', city: 'city5' }
// , { name: 'Bush Child 2', city: 'city5' }
// ]
like image 21
Mulan Avatar answered Jan 31 '23 08:01

Mulan