Я пытаюсь отсортировать массив парных объектов ключ-значение, используя индекс второго массива массивов.

Рассмотрим следующий код:

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)

Когда вы запускаете приведенный выше код, sorted сохраняет тот же порядок, что и исходная переменная quotes, и это выглядит так, как будто никакой сортировки не было!

Я чувствую, что я почти на месте, и мой код просто нуждается в небольшой настройке, чтобы заставить его работать.

1
braggs 21 Дек 2019 в 03:52

3 ответа

Лучший ответ

sheet - это массив массивов, поэтому sheet.indexOf что-нибудь , кроме массива, взятого из sheet, вернет -1.

Сначала преобразуйте sheet в массив строк:

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)

Или используйте .findIndex вместо 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)

Или, для лучшей вычислительной сложности (O(n log n)), преобразуйте sheet в объект, индексированный строкой, значениями которой являются индикаторы:

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)
3
CertainPerformance 21 Дек 2019 в 00:58

Вы не можете использовать indexOf, поскольку sheet является массивом массивов. Попробуйте использовать findIndex() и сравнить единственный элемент массива:

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);
1
mickl 21 Дек 2019 в 00:56

Немного другой подход (который должен быть более эффективным, чем использование .sort() для больших массивов), который вы могли бы использовать, если бы у вашего quotes массива были уникальные {root} объекты, заключался бы в создании new Map из вашего quotes массива а затем .map() ваш sheet массив {root} объектов выглядит так:

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)

Если у вас есть дубликаты, вы можете использовать .reduce() вместо new Map, а затем .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)
1
Nick Parsons 21 Дек 2019 в 01:05