0

I can't seem to find a neat solution to this fairly simple problem. I have an array of objects likes this:

let items = [{/* */}, {/* */}, {/* */}]

Additionally, i have an array containing new array indices that i want to apply to the above items:

const newIndices = [2,0,1]

Meaning items[0]'s new index is 2, items[1]'s new index is 0, etc...

Right now i am using forEach, but this method requires a temporary array:

const tempItems = []
newIndices.forEach((newIndex, oldIndex) => {
  tempItems[newIndex] = items[oldIndex]
})
items = tempItems

I'm almost certain there is a neat one liner for this problem. I've also tried mapping, but without luck.

4
  • 4
    Your current method is fine. I wouldn't change it. Don't worry about creating extra arrays/objects, usually - after all, code is usually easiest to understand when mutation is avoided. Commented Jan 23, 2021 at 15:21
  • Alternatively, you might consider using a Map rather than an array. Since the index seems to be important to your solution, you should keep in mind that order in arrays is a bit tricky. Arrays are not required to be dense, so iterating them cannot guarantee order. In most cases this doesn't really matter - unless the index is important to your logic :-) Commented Jan 23, 2021 at 15:26
  • @RandyCasburn Interesting fact. So, as long as my array is dense/filled i should be able to trust the index, right? I might look into using a Map instead some time in the future. Commented Jan 23, 2021 at 15:55
  • @JonasLittau - yep, just like most of us do. But now you know! Commented Jan 23, 2021 at 16:10

4 Answers 4

3

You could map the new index/value pairs with objects and assign to an array.

const
    items = ['foo', 'bar', 'baz'],
    newIndices = [2, 0, 1],
    result = Object.assign([], ...items.map((v, i) => ({ [newIndices[i]]: v })));

console.log(result); // bar baz foo

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

5 Comments

quick question, why { [newIndices[i]] : v} works but { newIndices[i] : v } doesn't ?
@mss, you need a computed property.
isn't newIndices[i] returning the number, which should become the key in the object for the provided value? I guess I am missing something, can you please provide me some reference.
@mss, please see here: computed property names
Thanks for the reference, my concept about object got more clear through your reference. correct me If I am wrong somewhere, basically the key value of object is taken as it is i.e literally the name of the key variable provided, but since here it was in the notation of accessing the index, it was not parsing it correctly, so we use [] notation to dynamically assign the value returned by the expression, nice I could even use return value of some function or complex expression through this as a key.
2

working code

let items = ['foo', 'bar', 'baz']
const newIndices = [2, 0, 1]

const result = items.map((item, index) => items[newIndices.indexOf(index)])

console.log(result)

1 Comment

This is the simplest version so far
1

One way is to use Array.prototype.reduce():

let items = ['foo', 'bar', 'baz']
const newIndices = [2,0,1]

const result = newIndices.reduce((acc, indice, i) => {
  acc[indice] = items[i]
  return acc
}, [])

console.log(result)

2 Comments

I've tried this ;) The item 'foo' should end up with index 2, but ends up at index 1.
Whoops. :D Read the question too hastily. I updated my answer.
1

let items = ['foo', 'bar', 'baz']
const newIndices = [2, 0, 1]
items = newIndices.map((index) => newIndices[index]).map((index) => items[index])

console.log(items)

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.