Search code examples
sortinglodash

Lodash orderBy on nested Arrays of objects


Have an array of objects with some nested properties:

const sports = [{
  name: "Basketball",
  leagues: [{
     createdAt: 1
  }, {
     createdAt: 2
  }]
},{
  name: "Soccer",
  leagues: [{
     createdAt: 3
  }, {
     createdAt: 4
  }]
}]

To get the array of object sorted by name DESC (Z->A) (non nested property) I do:

const sorted = _.orderBy(sports, item => item.name, ['desc']); 

The result is

[{ name: "Soccer", ... },{ name: "Basketball", ... }] 

What I am trying to achieve is to sort this object based on its nested array of objects leagues.createdAt DESC (assuming 1,2,3,4 are the correct timestamps):

[{
  name: "Soccer",
  leagues: [{
     createdAt: 4
  }, {
     createdAt: 3
  }]
},{
  name: "Basketball",
  leagues: [{
     createdAt: 2
  }, {
     createdAt: 1
  }]
}]

Tried to do smth like that:

const sorted = _.orderBy(sports, [(item) => item.leagues[0].createdAt], ["desc"])

but the order is not quite right:

enter image description here


Solution

  • You'll need to map the ordered array, and sort the leagues using _.orderBy(). I'm using _.flow() to create a function that first sorts the entire array, and then maps and sorts the leagues in each object.

    const { flow, orderBy, map } = _
    
    const fn = flow(
      arr => orderBy(arr, 'name', 'desc'),
      arr => map(arr,  ({ leagues, ...o }) => ({
        ...o,
        leagues: orderBy(leagues, 'createdAt', 'desc')
      }))
    )
    
    const sports = [{"name":"Basketball","leagues":[{"createdAt":1},{"createdAt":2}]},{"name":"Soccer","leagues":[{"createdAt":3},{"createdAt":4}]}]
    
    const result = fn(sports)
    
    console.log(result)
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>