Как отсортировать массив объектов на основе другого массива объектов - PullRequest
0 голосов
/ 05 февраля 2019

У меня есть массив динамического размера, который меняет свой порядок в зависимости от того, что было выбрано в последний раз в позиции 0 массива.Проблема в том, что я хочу сохранить исходный порядок массива.

Чтобы сделать это, я создал дополнительную переменную, которая установлена ​​в исходную сортировку массива.Хотя некоторые значения массива могут измениться после выбора элемента, свойство name никогда не изменяется.Я хочу использовать этот факт для сортировки нового массива в исходное положение.

let keepRateOrder = rates.sort((a, b) => {  
        return prevRates.indexOf(a.name) - prevRates.indexOf(b.name);
      });


const rates = [
{name:'UPS', isChoosen:true, cost:63 ...},
{name:'Mail', isChoosen:false, cost:23 ...},
{name:'FedEx', isChoosen:false, cost:33 ...}
]


const prevRates = [
{name:'Mail', isChoosen:false, cost:23 ...},
{name:'UPS', isChoosen:true, cost:63 ...},
{name:'FedEx', isChoosen:false, cost:33 ...}
]

Ответы [ 3 ]

0 голосов
/ 05 февраля 2019

Сначала используйте .map, чтобы преобразовать prevRates в массив только из name свойств, а затем вы можете использовать .sort на основе этого массива имен:

const prevRates = [
  {name:'Mail', isChoosen:false, cost:23 },
  {name:'UPS', isChoosen:true, cost:63 },
  {name:'FedEx', isChoosen:false, cost:33 }
];
const rates = [
  {name:'UPS', isChoosen:true, cost:63 },
  {name:'Mail', isChoosen:false, cost:23 },
  {name:'FedEx', isChoosen:false, cost:33 }
];

const prevRatesNames = prevRates.map(({ name }) => name);
rates.sort((a, b) => (
  prevRatesNames.indexOf(a.name) - prevRatesNames.indexOf(b.name)
));
console.log(rates);

Помните, что .sort сортирует на месте - если вы сделаете

let keepRateOrder = rates.sort...

, тогда keepRateOrder будет простоеще одна ссылка на массив rates.Если вам нужна копия, а не мутировавший исходный массив rates, то сначала вам нужно будет скопировать rates:

const keepRateOrder = rates.slice().sort...
0 голосов
/ 05 февраля 2019

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

0 голосов
/ 05 февраля 2019

Это можно решить с помощью findIndex.В следующем примере сортировка будет помещать Mail первым согласно массиву prevRates:

const rates = [
  {name:'UPS', isChoosen:true, cost:63},
  {name:'Mail', isChoosen:false, cost:23},
  {name:'FedEx', isChoosen:false, cost:33}
];

const prevRates = [
  {name: 'Mail'},
  {name: 'UPS'},
  {name: 'FedEx'},
];

let keepRateOrder = rates.sort((a, b) => {
  return prevRates.findIndex(p => p.name === a.name) - prevRates.findIndex(p => p.name === b.name);
});

console.log(keepRateOrder);

Вы можете сделать то же самое с indexOf, если сначала вы map.Это приводит к несколько более чистому коду:

const rates = [
  {name:'UPS', isChoosen:true, cost:63},
  {name:'Mail', isChoosen:false, cost:23},
  {name:'FedEx', isChoosen:false, cost:33}
];

const prevRates = [
  {name: 'Mail'},
  {name: 'UPS'},
  {name: 'FedEx'},
].map(x => x.name);

let keepRateOrder = rates.sort((a, b) => {
  return prevRates.indexOf(a.name) - prevRates.indexOf(b.name);
});

console.log(keepRateOrder);

И вот еще одно решение, использующее хэш исходных индексов, созданный с использованием reduceRight:

const rates = [
  {name:'UPS', isChoosen:true, cost:63},
  {name:'Mail', isChoosen:false, cost:23},
  {name:'FedEx', isChoosen:false, cost:33}
]

const prevRates = [
  {name: 'Mail'},
  {name: 'UPS'},
  {name: 'FedEx'},
].reduceRight((a, x, i) => (a[x.name] = i, a), {});

let keepRateOrder = rates.sort((a, b) => {
  return prevRates[a.name] - prevRates[b.name];
});

console.log(keepRateOrder);

Поскольку вы сказали, что элементы могут быть добавлены или удалены из исходного массива, обратите внимание, что все вышеперечисленные решения будут размещать новые элементы первыми (так как их индекс в prevRates массив будет возвращен как -1).Если вы хотите, чтобы новые элементы появлялись в конце, вам нужно сделать что-то вроде этого:

const rates = [
  {name:'UPS', isChoosen:true, cost:63},
  {name:'Mail', isChoosen:false, cost:23},
  {name:'Foo'},
  {name:'FedEx', isChoosen:false, cost:33},
];

const prevRates = [
  {name: 'Mail'},
  {name: 'UPS'},
  {name: 'FedEx'},
].map(x => x.name);

let keepRateOrder = rates.sort((a, b) => {
  const aIndex = prevRates.indexOf(a.name);
  const bIndex = prevRates.indexOf(b.name);
  return (aIndex === -1 ? Number.MAX_VALUE : aIndex) - (bIndex === -1 ? Number.MAX_VALUE : bIndex);
});

console.log(keepRateOrder);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...