Home > OS >  Javascript sort object by key within nested objects
Javascript sort object by key within nested objects

Time:08-17

I have the following object:

{
  4: {
    1: [
      { order: 1, name: 'Test 4' }
    ]
  },
  0: {
    15: [
      { order: 7, name: 'Test 1' },
      { order: 3, name: 'Test 3' },
    ],
    12: { 
      { order: 1, name: 'Test 2' }
    }
  }
}

Essentially what I am trying to achieve is to order this by the keys and then order further by the order property from within the nested value. So in turn I get the following output:

{
  0: {
    12: { 
      { order: 1, name: 'Test 2' }
    },
    15: [
      { order: 3, name: 'Test 3' },
      { order: 7, name: 'Test 1' },
    ]
  },
  4: {
    1: [
      { order: 1, name: 'Test 4' }
    ]
  }
}

I then want to completely flatten this so it's without any of the outer object and just the data within the order, the outcome would then be:

[
  { name: 'Test 2' },
  { name: 'Test 3' },
  { name: 'Test 1' },
  { name: 'Test 4' }
]

I imagine this would be some kind of recursive operation which I need to do and I originally did it with something like the following but it got a bit messy:

Object.keys(obj)
  .sort()
  .reduce((acc, key) => { acc[key] = obj[key]; return acc; }, {});

CodePudding user response:

You can sort each obj by keys using Object.keys(obj).sort() and then access each element by its key.

Do this 2 times to get the array of object

const obj = {
  4: {
    1: [
      { order: 1, name: 'Test 4' }
    ]
  },
  0: {
    15: [
      { order: 7, name: 'Test 1' },
      { order: 3, name: 'Test 3' },
    ],
    12: [ 
      { order: 1, name: 'Test 2' }
    ]
  }
}

let flatItems = []
const keys = Object.keys(obj).sort()

for (const key of keys){
  const subObj = obj[key]
  
  const subKeys = Object.keys(subObj).sort()
  
  for(const subKey of subKeys){
   flatItems = flatItems.concat(subObj[subKey].sort((a, b) => a.order - b.order))
  }
}

console.log(flatItems)

CodePudding user response:

You could create a recursive function (sortEntries) that takes your object and grabs the entries from it. Using the key component of the entries, you can sort based on that. Once you've sorted the entries, you can .flatMap() the result of recursively sorting your nested object value by calling the sortEntries function again. For the base case (termination case), you can stop the recursion once you've found a value that is an array, which for that you can sort by the order property for your objects and then .map() each object to extract only the name property. Each array returned by .map() will be merged together into one resulting array due to the previous .flatMap() call:

const obj = { 4: { 1: [ { order: 1, name: 'Test 4' } ] }, 0: { 15: [ { order: 7, name: 'Test 1' }, { order: 3, name: 'Test 3' }, ], 12: [ { order: 1, name: 'Test 2' } ] } };

const sortEntries = (obj) => {
  return Array.isArray(obj)
    ? obj.slice().sort((a, b) => a.order - b.order).map(({name}) => ({name}))
    : Object.entries(obj).sort(([a], [b]) => a - b).flatMap(([, val]) => sortEntries(val));
}

const res = sortEntries(obj);
  
console.log(res);

  • Related