#javascript #arrays #sorting
#javascript #массивы #сортировка
Вопрос:
Я хочу отсортировать массив массивов на основе массива, а затем по длине элементов в массиве.
Возьмите следующий основной массив сортировки:
const key = [
"meraki",
"gsuite",
"active directory",
"sophos",
"manageengine"
]
Я хочу взять массив, который напоминает:
const raw = [
["manageengine"],
["sophos"],
["active directory"],
["gsuite"],
["meraki"],
["sophos", "manageengine"],
["active directory", "sophos"],
["active directory", "manageengine"],
["gsuite", "active directory"],
["gsuite", "sophos"],
["gsuite", "manageengine"],
["meraki", "gsuite"],
["meraki", "active directory"],
["meraki", "sophos"],
["meraki", "manageengine"],
["active directory", "sophos", "manageengine"],
["gsuite", "active directory", "sophos"],
["gsuite", "active directory", "manageengine"],
["gsuite", "sophos", "manageengine"],
["meraki", "gsuite", "active directory"],
["meraki", "gsuite", "sophos"],
["meraki", "active directory", "sophos"],
["meraki", "gsuite", "manageengine"],
["meraki", "active directory", "manageengine"],
["meraki", "sophos", "manageengine"],
["gsuite", "active directory", "sophos", "manageengine"],
["meraki", "gsuite", "active directory", "sophos"],
["meraki", "gsuite", "active directory", "manageengine"],
["meraki", "gsuite", "sophos", "manageengine"],
["meraki", "active directory", "sophos", "manageengine"],
["meraki", "gsuite", "active directory", "sophos", "manageengine"]
];
В приведенном выше примере я хочу raw
, чтобы массив был отсортирован соответственно каждому элементу в key
массиве. Моей первой попыткой было сделать что-то вроде:
const result = [];
for (const name of result) {
const sorted = keys.filter((s) => s[0] === name);
result.push(...sorted);
}
result.sort((a, b) => a.length - b.length);
Однако это учитывает только первый элемент в массиве, а не сортировку остальных элементов.
Комментарии:
1. Является ли ключ постоянным, или он изменяется с каким-либо вводом или ожидаемыми изменениями кода?
2. Я думаю, вы хотите
for (const name of raw)
, тогда, в этом цикле,const sorted = name.sort((a,b) => keys.indexOf(a) - keys.indexOf(b))
. Вероятно, вам понадобится какая-то рекурсивная сортировка для внешнего массива, поскольку его нужно сортировать по длине, а затем по содержимому каждого массива.3. Во-первых, ваш «результат» содержит разные элементы из «необработанного» массива — третья строка,
["sophos", "active directory"]
похоже, стала["meraki", "active directory"]
. Это просто опечатка? Во-вторых, вашим требованием было сортировать по ключу, а затем по длине , но ваш вывод — по длине, а затем по ключу — что это? Должны ли все те, которые начинаются с «meraki», отображаться первыми и сортироваться по длине, или все те, у которых есть только одна запись, должны отображаться первыми, отсортированными по ключу?4. @ATD — Хороший улов — я обновил данные.
Ответ №1:
Для сортировки вы должны сначала проверить длину. Если оба равны, мы должны проверить позиции индекса первого элемента a
/ b
внутри key
. Если это одно и то же, перейдите к следующему элементу в обоих массивах.
В этом ответе используется тот факт, 0
что это ложное значение. Примерами являются: 0 || -1 //=> -1
и 1 || -1 //=> 1
const key = ["meraki", "active directory", "sophos"];
const raw = [
["meraki"],
["active directory"],
["sophos", "active directory"],
["active directory", "sophos"],
["sophos"],
["meraki", "active directory", "sophos"],
];
raw.sort((a, b) => (
a.length - b.length || a.reduce((diff, _, i) => (
diff || key.indexOf(a[i]) - key.indexOf(b[i])
), 0)
));
console.log(raw);
console.table(raw); // check browser console
Комментарии:
1. Другим вариантом было бы
a.reduce((diff, a, i) => diff || key.indexOf(a) - key.indexOf(b[i]), 0)
вместоupto(a.length).reduce(...)
, но я презираю асимметрию в этом решении.
Ответ №2:
Рассмотрим следующий подход
const key = [
"meraki",
"active directory",
"sophos"
]
const raw = [
["sophos"],
["meraki"],
["active directory"],
["sophos", "active directory"],
["active directory", "sophos"],
["meraki", "active directory", "sophos"]
]
const compareThis = (a, b) => {
if (a.length !== b.length) {
return a.length - b.length
}
let itemFound = 0;
for (let keyIndex in key) {
for (let aIndex in a ) {
if(a[aIndex] === key[keyIndex]) {
itemFound = -1;
break;
}
if(b[aIndex] === key[keyIndex]) {
itemFound = 1;
break;
}
}
if(itemFound !== 0) { break }
}
return itemFound;
}
const sortedData = raw.sort(compareThis)
console.log(sortedData)
Комментарии:
1. Примечание: вам не хватает ‘var’ в циклах ‘for’
2. Я думаю, что теперь он перевернут.
3. Не могли бы вы предоставить более широкий массив для отладки?