0

I have two arrays, one containings some items, and another containings sorted ids of those items like so:

const items = [
    { id: 1, label: 'foo' },
    { id: 2, label: 'bar' },
    { id: 3, label: 'lorem' },
    { id: 4, label: 'ipsum' },
]

const sortedItemIds = [4, 3, 2, 1]

I want to have another array containing items sorted by their id like so:

const sortedItems = [
    { id: 4, label: 'ipsum' },
    { id: 3, label: 'lorem' },
    { id: 2, label: 'bar' },
    { id: 1, label: 'foo' },
]

Note that the order may not be whatever, not asc or desc

I made this piece of code, that works pretty well as it:

let sortedItems = []
sortedItemIds.map((itemId, index) => {
    items.map(item) => {
        if (item.id === itemId) {
            sortedItems[index] = item
        }
    }
})

I feel like I may run into issues with a large array of items, due to the nested Array.map() functions

Is there a better way / best practice for this scenario?

2
  • 3
    None of the .map() calls return anything, hence they are not the right tool for the task Commented Oct 1, 2018 at 16:59
  • Possible duplicate of Javascript - sort array based on another array Commented Oct 1, 2018 at 17:00

2 Answers 2

3

You could create one object where keys are ids and then use that object get values by id.

const items = [{ id: 1, label: 'foo' },{ id: 2, label: 'bar' },{ id: 3, label: 'lorem' },{ id: 4, label: 'ipsum' }]
const sortedItemIds = [4, 3, 2, 1]

const obj = {}
items.forEach(o => obj[o.id] = o);

const sortedItems = sortedItemIds.map(e => Object.assign({}, obj[e]));
console.log(sortedItems)

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

3 Comments

The Object.assign({}, ...) seems unnecessary here. OP has not mentioned any requirement about performing a shallow clone of each of the objects and in any case the use of Object.assign() should at least have a brief explanation.
What if the item's id is not an Int, but let's say a String? And in case of mixed types?
Nevermind I didn't understand your code. Seems pretty good to me now!
1

You don't need the function map for doing this, just use the find Array.indexOf and Array.sort in order to sort it.

const items = [{ id: 1, label: 'foo' },{ id: 2, label: 'bar' },{ id: 3, label: 'lorem' },{ id: 4, label: 'ipsum' }],
      sortedItemIds = [4, 3, 2, 1];

items.sort((a, b) => sortedItemIds.indexOf(a.id) - sortedItemIds.indexOf(b.id));
console.log(items);
.as-console-wrapper { max-height: 100% !important; top: 0; }

2 Comments

Looks like this solution works well. I modified it for my needs, adding .slice() as I didn't want to change my first array. const sortedItems = items.slice().sort((a, b) => sortedItemIds.indexOf(a.id) - sortedItemIds.indexOf(b.id));.
The efficiency of this is O(n^2 log n), whereas @NenadVracar's answer is ~O(n) assuming approximately constant time for key lookup. Not exactly an optimized implementation.

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.