Как отсортировать массив объектов с метками по другому массиву меток? - PullRequest
2 голосов
/ 29 октября 2019

Я хочу отсортировать массив объектов с метками, например

var arrayToBeSorted = [{label: 'firstLabel', value: 123}, {label: 'secondLabel', value: 456}, {label: 'thirdLabel', value: 789}]

и массив меток в качестве базовой линии, например

var labels = ['secondLabel', 'thirdLabel', 'fourthLabel', 'firstLabel']

Теперь я хочу отсортироватьмой первый массив, так что объекты в нем следуют порядку меток во втором массиве labels.

Я знаю базовый механизм сортировки с пользовательскими компараторами, такими как

CustomComparator: function(a, b) {
  if (a[0].length > b[0].length) return -1;
  if (a[0].length < b[0].length) return 1;
  return 0;
}

, но у меня естьпонятия не имею, как это преобразовать.

В своем исследовании я нашел это решение для stackoverflow, закодированное в ruby, но я не знаю, есть ли подобная опция в javascript.

Я ценю любую помощь, потраченную на это достаточно времени.

Ответы [ 4 ]

2 голосов
/ 29 октября 2019

Существует несколько подходов:

  1. Использование indexOf для многократного поиска в массиве labels

  2. Использование карты такпоиск индекса метки происходит быстрее

Вот пример использования indexOf (в ES2015 +):

arrayToBeSorted.sort((a, b) => labels.indexOf(a.label) - labels.indexOf(b.label));

Live Copy:

var arrayToBeSorted = [{label: 'firstLabel', value: 123}, {label: 'secondLabel', value: 456}, {label: 'thirdLabel', value: 789}];

var labels = ['secondLabel', 'thirdLabel', 'fourthLabel', 'firstLabel'];

arrayToBeSorted.sort((a, b) => labels.indexOf(a.label) - labels.indexOf(b.label));

console.log(arrayToBeSorted);

Обратите внимание, что indexOf вернет -1, если метка не существует в labels, что приведет к появлению неизвестных меток в начале результата. Если вы хотите, чтобы они были в конце, вместо этого проверьте -1 и замените его на Infinity.

Вот пример использования карты для ускорения поиска этих индексов (в ES2015 +):

const map = new Map(labels.map((label, index) => [label, index]));
arrayToBeSorted.sort((a, b) => {
    let aindex = map.get(a.label);
    if (aindex === null) {
        aindex = -1; // Or Infinity if you want them at the end
    }
    let bindex = map.get(b.label);
    if (bindex === null) {
        bindex = -1; // ""
    }
    return aindex - bindex;
});

Live Copy:

var arrayToBeSorted = [{label: 'firstLabel', value: 123}, {label: 'secondLabel', value: 456}, {label: 'thirdLabel', value: 789}];

var labels = ['secondLabel', 'thirdLabel', 'fourthLabel', 'firstLabel'];

const map = new Map(labels.map((label, index) => [label, index]));
arrayToBeSorted.sort((a, b) => {
    let aindex = map.get(a.label);
    if (aindex === null) {
        aindex = -1; // Or Infinity if you want them at the end
    }
    let bindex = map.get(b.label);
    if (bindex === null) {
        bindex = -1; // ""
    }
    return aindex - bindex;
});

console.log(arrayToBeSorted);

Это написано для ясности и во избежание повторного поиска меток в обратном вызове. Это может быть более кратким за счет второго поиска меток на карте:

const map = new Map(labels.map((label, index) => [label, index]));
arrayToBeSorted.sort((a, b) => {
    const aindex = map.has(a.label) ? map.get(a.label) : -1; // Or Infinity if you want them at the end
    const bindex = map.has(b.label) ? map.get(b.label) : -1; // "
    return aindex - bindex;
});

Live Copy:

var arrayToBeSorted = [{label: 'firstLabel', value: 123}, {label: 'secondLabel', value: 456}, {label: 'thirdLabel', value: 789}];

var labels = ['secondLabel', 'thirdLabel', 'fourthLabel', 'firstLabel'];

const map = new Map(labels.map((label, index) => [label, index]));
arrayToBeSorted.sort((a, b) => {
    const aindex = map.has(a.label) ? map.get(a.label) : -1; // Or Infinity if you want them at the end
    const bindex = map.has(b.label) ? map.get(b.label) : -1; // "
    return aindex - bindex;
});

console.log(arrayToBeSorted);

Это может быть даже:

const map = new Map(labels.map((label, index) => [label, index]));
arrayToBeSorted.sort((a, b) =>
    (map.has(a.label) ? map.get(a.label) : -1) - (map.has(b.label) ? map.get(b.label) : -1)
);

... но для меня это усложняет жизнь при отладке и т. Д.

2 голосов
/ 29 октября 2019

Вам необходимо предоставить приоритет значениям в соответствии с вторым массивом. здесь мы строим карту из имени второго массива в качестве ключа и индекса в качестве приоритета. так что вы можете использовать Map и default value и sort

var arrayToBeSorted = [{label: 'firstLabel', value: 123}, {label: 'secondLabel', value: 456}, {label: 'thirdLabel', value: 789}]
var labels = ['secondLabel', 'thirdLabel', 'fourthLabel', 'firstLabel']

let mapper = new Map(labels.map((v, i) => [v, i + 1]))

let final = arrayToBeSorted.sort((a, b) => {
  return (mapper.get(a.label) || Infinity) - (mapper.get(b.label) || Infinity)
})

console.log(final)
0 голосов
/ 29 октября 2019

Прямо вперед с использованием sort-array .

const sortArray = require('sort-array')

const arrayToBeSorted = [
  {label: 'firstLabel', value: 123},
  {label: 'secondLabel', value: 456},
  {label: 'thirdLabel', value: 789}
]

sortArray(arrayToBeSorted, {
  by: 'label',
  order: 'labelOrder',
  customOrders: {
    labelOrder: ['secondLabel', 'thirdLabel', 'fourthLabel', 'firstLabel']
  }
})

console.log(arrayToBeSorted)

Печать этого вывода:

[
  { label: 'secondLabel', value: 456 },
  { label: 'thirdLabel', value: 789 },
  { label: 'firstLabel', value: 123 }
]
0 голосов
/ 29 октября 2019

Вы можете создать свой заказ и заказать по нему:

var arrayToBeSorted = [
    {label: 'firstLabel', value: 123}, 
    {label: 'secondLabel', value: 456}, 
    {label: 'thirdLabel', value: 789}
];

let order = { secondLabel: 1, thirdLabel: 2, fourthLabel: 3, firstLabel: 4 };

arrayToBeSorted.sort((a, b) => {
  return order[a.label] - order[b.label];
});

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