0

I have an object with the following structure:

root_object: {
    ITEM_ONE: {
        order: 2,
        prop_one: '123',
        prop_two: '456',
    },
    ITEM_TWO: {
        order: 1,
        prop_one: '789',
        prop_two: '321',
    },
    ITEM_THREE: {
        order: 3,
        prop_one: '654',
        prop_two: '987',
    },
}

As an end result, I will need to get the list of keys:

['ITEM_ONE', 'ITEM_TWO', 'ITEM_THREE']

BUT they need to be ordered based on the property order, which will result as:

['ITEM_TWO', 'ITEM_ONE', 'ITEM_THREE']

I prefer to use the _lodash library for this purpose, but I'm not even sure how to start with it, since the structure for the root_object is an object and not a list.

1
  • What did you try ? Show us some code who give you error ? Or solutions you try ? We're not here for doing your job. Commented May 9, 2019 at 18:17

6 Answers 6

4

You can do this with plain js using sort method and Object.keys.

const data = {"ITEM_ONE":{"order":2,"prop_one":"123","prop_two":"456"},"ITEM_TWO":{"order":1,"prop_one":"789","prop_two":"321"},"ITEM_THREE":{"order":3,"prop_one":"654","prop_two":"987"}}
const res = Object.keys(data).sort((a, b) => data[a].order - data[b].order)
console.log(res)

Sign up to request clarification or add additional context in comments.

Comments

2

Just use sort with a callback function, like so:

var root = {ITEM_ONE:{order:2,prop_one:'123',prop_two:'456'},ITEM_TWO:{order:1,prop_one:'789',prop_two:'321'},ITEM_THREE:{order:3,prop_one:'654',prop_two:'987'}};

var keys = Object.keys(root).sort((a, b) => root[a].order - root[b].order);
console.log(...keys);

For a lodash solution, use toPairs, sortBy, then map to get the keys:

var root = {ITEM_ONE:{order:2,prop_one:'123',prop_two:'456'},ITEM_TWO:{order:1,prop_one:'789',prop_two:'321'},ITEM_THREE:{order:3,prop_one:'654',prop_two:'987'}};

console.log(..._.map(_.sortBy(_.toPairs(root), '1.order'), 0));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

Comments

1

You could sort the keys by taking the value for sorting.

var object = { root_object: { ITEM_ONE: { order: 2, prop_one: '123', prop_two: '456' }, ITEM_TWO: { order: 1, prop_one: '789', prop_two: '321' }, ITEM_THREE: { order: 3, prop_one: '654', prop_two: '987' } } },
    keys = Object.keys(object.root_object);
    
keys.sort((a, b) => object.root_object[a].order - object.root_object[b].order);

console.log(keys);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Comments

1

Just use Array.prototype.sort() on the array of Object.keys(root_object):

const root_object = {
    ITEM_ONE: {
        order: 2,
        prop_one: '123',
        prop_two: '456',
    },
    ITEM_TWO: {
        order: 1,
        prop_one: '789',
        prop_two: '321',
    },
    ITEM_THREE: {
        order: 3,
        prop_one: '654',
        prop_two: '987',
    },
}

let result = Object.keys(root_object).sort((a,b) => root_object[a].order - root_object[b].order);

console.log(result);

Comments

1

This is an O(n) solution (sort is O(nlogn)) that works only for unique order values.

You can use lodash to map the values of each property to the order ({ ITEM_ONE: 2, ITEM_TWO: 1, ... }), then invert the keys and values ({ 1: ITEM_TWO, 2: ITEM_ONE, ... }), and extract the values. This will get you the items in the right order:

const { flow, partialRight: pr, mapValues, invert, values } = _

const fn = flow(
  pr(mapValues, 'order'), // convert to { ITEM_ONE: 2, ITEM_TWO: 1, ... }
  invert, // convert to { 1: ITEM_TWO, 2: ITEM_ONE, ... }
  values // get the array of keys
)

const root_object = {"ITEM_ONE":{"order":2,"prop_one":"123","prop_two":"456"},"ITEM_TWO":{"order":1,"prop_one":"789","prop_two":"321"},"ITEM_THREE":{"order":3,"prop_one":"654","prop_two":"987"}}

const result = fn(root_object)
  
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>

In vanilla JS by convert the object to entries, map the entries to the form of [order, key], convert the entries to object with Object.fromEntries() (not supported by IE/Edge), and then get the values:

const fn = o => Object.values(Object.fromEntries(
  Object.entries(o).map(([k, { order }]) => [order, k])
))

const root_object = {"ITEM_ONE":{"order":2,"prop_one":"123","prop_two":"456"},"ITEM_TWO":{"order":1,"prop_one":"789","prop_two":"321"},"ITEM_THREE":{"order":3,"prop_one":"654","prop_two":"987"}}

const result = fn(root_object)
  
console.log(result)

2 Comments

The invert is a clever way to sort, though I don't think it's safe if order values could be duplicated.
@p.s.w.g - indeed. I'll add a note about that.
0

You can use Object.keys along with Array.map and Array.sort

const root_object = {
    ITEM_ONE: {
        order: 2,
        prop_one: '123',
        prop_two: '456',
    },
    ITEM_TWO: {
        order: 1,
        prop_one: '789',
        prop_two: '321',
    },
    ITEM_THREE: {
        order: 3,
        prop_one: '654',
        prop_two: '987',
    },
}

let rootArr = [];

let sortedRootObject = Object.keys(root_object).map(key => rootArr.push(root_object[key])).sort((a, b) => rootArr[b.order] - rootArr[a.order])

console.log(sortedRootObject)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.