1

I am trying to sort an array of key-value paired objects using the index of a second array of arrays.

Consider the following code:

const sheet = [['ES'], ['MES'], ['NQ'], ['MNQ']] // sort in this order
const quotes = [{root: 'MNQ'}, {root: 'MES'}, {root: 'ES'}, {root: 'NQ'}] // sort these objects

const sorted = quotes.sort((a, b) => {
  return sheet.indexOf(a.root) - sheet.indexOf(b.root)
})

console.log(sorted)

When you run the above code, sorted has retained the same order as the original quotes variable and it appears as if no sort has taken place!

I feel like I'm almost there and my code just needs a small tweak to make it work.

3
  • @CertainPerformance, can you please explain the reason for the edit, so I don't make the same mistake again? Commented Dec 21, 2019 at 0:59
  • See meta.stackexchange.com/q/2950 - it's not a big problem, but Stack Overflow is meant to be a reference site, not a discussion forum, so "thanks" etc is just noise (and we're supposed to remove them from posts when we see them) Commented Dec 21, 2019 at 1:01
  • Noted and will be less 'chatty' from now on Commented Dec 21, 2019 at 1:04

3 Answers 3

3

sheet is an array of arrays, so sheet.indexOf anything other than an array taken from sheet will return -1.

Transform sheet to an array of strings first:

const sheet = [['ES'], ['MES'], ['NQ'], ['MNQ']]
  .map(([str]) => str);
const quotes = [{root: 'MNQ'}, {root: 'MES'}, {root: 'ES'}, {root: 'NQ'}] // sort these objects

const sorted = quotes.sort((a, b) => {
  return sheet.indexOf(a.root) - sheet.indexOf(b.root)
})

console.log(sorted)

Or use .findIndex instead of indexOf:

const sheet = [['ES'], ['MES'], ['NQ'], ['MNQ']];
const quotes = [{root: 'MNQ'}, {root: 'MES'}, {root: 'ES'}, {root: 'NQ'}] // sort these objects

const sorted = quotes.sort((a, b) => {
  return sheet.findIndex(arr => arr[0] === a.root) - sheet.findIndex(arr => arr[0] === b.root)
})

console.log(sorted)

Or, for better computational complexity (O(n log n)), transform sheet into an object indexed by string, whose values are the indicies:

const sheet = [['ES'], ['MES'], ['NQ'], ['MNQ']];
const sheetObj = {};
for (const [i, [str]] of sheet.entries()) {
  sheetObj[str] = i;
}
const quotes = [{root: 'MNQ'}, {root: 'MES'}, {root: 'ES'}, {root: 'NQ'}] // sort these objects

const sorted = quotes.sort((a, b) => sheetObj[a.root] - sheetObj[b.root]);

console.log(sorted)

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

1 Comment

Bingo! Thank you very much @CertainPerformance. I will accept your answer as soon as the 15 minute timer is over
1

You cannot use indexOf since sheet is an array of arrays. Try using findIndex() and comparing the only array element:

const sheet = [['ES'], ['MES'], ['NQ'], ['MNQ']] // sort in this order
const quotes = [{root: 'MNQ'}, {root: 'MES'}, {root: 'ES'}, {root: 'NQ'}] // sort these objects

let sorted = quotes.sort((a, b) => {
  return sheet.findIndex(([x]) => x === a.root) - sheet.findIndex(([x]) => x === b.root);
})

console.log(sorted);

Comments

1

A slightly different approach (which should be more efficient than using .sort() for larger arrays) you could use if your quotes array has unique {root} objects would be to make a new Map from your quotes array and then .map() your sheet array the {root} objects like so:

const sheet = [['ES'], ['MES'], ['NQ'], ['MNQ']];
const quotes = [{root: 'MNQ'}, {root: 'MES'}, {root: 'ES'}, {root: 'NQ'}] // sort these objects

const lut = new Map(quotes.map(({root}) => [root, {root}]));
const sorted = sheet.map(([s]) => lut.get(s));
console.log(sorted)

If you're you can have duplicates, you can use .reduce() instead of a new Map, and then .flatMap():

const sheet = [['ES'], ['MES'], ['NQ'], ['MNQ']];
const quotes = [{root: 'MNQ'}, {root: 'MES'}, {root: 'ES'}, {root: 'NQ'}, {root: 'MES'}] // sort these objects

const lut = quotes.reduce((acc, {root}) => {
  acc[root] = [...(acc[root] || []), {root}];
  return acc;
}, {});

const sorted = sheet.flatMap(([s]) => lut[s]);
console.log(sorted)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.