-1

I've got the following object which I'd like to sort by its priority fields.

{
    anchor_block: {
        label: 'Anker-Block',
        priority: 100,
        description: ...,
        fields: ...
    },
    categories_block: {
        label: 'Categories-Block',
        description: ...,
        fields: ...
    },
    contact_block: {
        label: 'Kontakt-Block',
        description: ...,
        fields: ...
    },
    employee_block: {
        label: 'Mitarbeiter-Block',
        priority: 90,
        description: ...,
        fields: ...
    }
}

I've tried to sort them with lodash:

_.orderBy(blocks, ['priority'], ['desc']);

But this solution removes the all the keys from my objects (because it returns an array) and it also puts the ones without a priority field on top:

[
    {
        label: 'Categories-Block',
        description: ...,
        fields: ...
    },
    {
        label: 'Kontakt-Block',
        description: ...,
        fields: ...
    },
    {
        label: 'Anker-Block',
        priority: 100,
        description: ...,
        fields: ...
    },
    {
        label: 'Mitarbeiter-Block',
        priority: 90,
        description: ...,
        fields: ...
    },
]

Does any one of you have an idea on how to solve this with lodash? I'd like to avoid iterating it myself, because I'm sure it's possible, I just don't get my head around it.

Spomsoree
  • 123
  • 1
  • 8
  • 3
    Objects aren't ordered in JavaScript. – Barmar Dec 30 '19 at 18:02
  • 1
    @Barmar Are you sure? We used to say that the order of keys couldn't be guaranteed when iterating over an object but that doesn't seem to be true anymore. If keys are inserted in a specific order then can't we say that objects can be ordered? – customcommander Dec 30 '19 at 18:12
  • 1
    It's somewhat true. https://stackoverflow.com/questions/30076219/does-es6-introduce-a-well-defined-order-of-enumeration-for-object-properties – Barmar Dec 30 '19 at 18:14
  • 1
    since es2020, property order is well-defined in all cases. If there are no integer-index properties and no symbols involved, that order [can be freely manipulated](https://stackoverflow.com/questions/5467129/sort-javascript-object-by-key), but this does by no means say that one should. Use a proper data structure, that fits the task, not property order of objects. – ASDFGerte Dec 30 '19 at 18:19
  • Thank you very much. What kind data structure would you choose? Should I add them to an array, or how do you preserve the order? – Spomsoree Dec 31 '19 at 08:11

1 Answers1

2

Updated Answer: Approach is to store all keys, sort them according to the order you desire, and then use those keys to retrieve values from the original object in desired order.

let obj = {
    anchor_block: {
        label: 'Anker-Block',
        priority: 100,
        description: '...',
        fields: '...'
    },
    categories_block: {
        label: 'Categories-Block',
        description: '...',
        fields: '...'
    },
    contact_block: {
        label: 'Kontakt-Block',
        description: '...',
        fields: '...'
    },
    employee_block: {
        label: 'Mitarbeiter-Block',
        priority: 90,
        description: '...',
        fields: '...'
    }
}
/*
    Plain JS, no Lodash
*/

let sortedKeys = Object.keys(obj);
sortedKeys.sort((key1, key2) => {
    let p1 = obj[key1].priority || 0, p2 = obj[key2].priority || 0;
    if(p1<p2)
        return 1; // Put key2 first in sorted order
    return -1; // Else, put key1 first in sorted order
    /*
        For ascending order, do this
        if(p1<p2)
            return -1;
        return 1;
    */
})

sortedKeys.forEach(key => {
    console.log(key,"-->",obj[key]);
})

Output

anchor_block --> { label: 'Anker-Block',
  priority: 100,
  description: '...',
  fields: '...' }
employee_block --> { label: 'Mitarbeiter-Block',
  priority: 90,
  description: '...',
  fields: '...' }
categories_block --> { label: 'Categories-Block', description: '...', fields: '...' }
contact_block --> { label: 'Kontakt-Block', description: '...', fields: '...' }
Ajay Dabas
  • 1,404
  • 1
  • 5
  • 15
  • Thank you for your effort, but this does not quite work as I expected. Doesn't it just shift the neighbors? I think this needs to be run as many times as there are items in the object, to get the needed result. – Spomsoree Dec 31 '19 at 08:19
  • `Doesn't it just shift the neighbors?`, please elaborate on this point. If the result is not your expected output, please provide a sample output. – Ajay Dabas Dec 31 '19 at 08:25
  • Thats what I thought, the first time I tested this snipped. I've created a jsfiddle now (https://jsfiddle.net/40xh89vb/1/) which I can't get to order the items. – Spomsoree Dec 31 '19 at 08:58
  • 1
    You're right, there was an error in my sort comparator function. I've fixed it in my updated answer. – Ajay Dabas Dec 31 '19 at 10:27
  • Oh wow, thank you. It works exactly as I hoped: https://jsfiddle.net/bLd628qj/1/ – Spomsoree Dec 31 '19 at 11:26
  • 1
    Glad I could help! – Ajay Dabas Dec 31 '19 at 11:30