#javascript #arrays #sorting
Вопрос:
У меня есть 2D массив, записи в котором представляют сотрудника, включая имя его менеджера, примерно так:
var array = [["Name", "Manager"],
["Leonard", "Penny"],
["Penny", "Professor Proton"],
["Sheldon", "Bernadette"],
["Raj", "Penny"],
["Professor Proton", "Professor Proton"],
["Howard", "Bernadette"],
["Bernadette", "Professor Proton"]]
Если сотрудник и менеджер-одно и то же, это означает, что этот человек занимает самое высокое место в иерархии. Чего я хочу добиться, так это отсортировать каждого сотрудника ниже его руководителя в алфавитном порядке. Другими словами, результат, который я хочу, это:
[["Name", "Manager"],
["Professor Proton", "Professor Proton"],
["Bernadette", "Professor Proton"],
["Howard", "Bernadette"],
["Sheldon", "Bernadette"],
["Penny", "Professor Proton"],
["Leonard", "Penny"],
["Raj", "Penny"]]
Моя попытка состояла в том, чтобы использовать array.sort(compare)
следующую функцию «сравнить» :
var array = [
["Name", "Manager"],
["Leonard", "Penny"],
["Penny", "Professor Proton"],
["Sheldon", "Bernadette"],
["Raj", "Penny"],
["Professor Proton", "Professor Proton"],
["Howard", "Bernadette"],
["Bernadette", "Professor Proton"]
];
function compare(a, b) {
if (a[0] === a[1]) {
return -1;
}
if (b[0] === b[1]) {
return 1;
}
if (a[0] === b[1]) {
return -1;
}
if (b[0] === a[1]) {
return 1;
}
if (a[0].toLowerCase() < b[0].toLowerCase()) {
return -1;
}
if (a[0].toLowerCase() > b[0].toLowerCase()) {
return 1;
}
return 0;
}
console.log(array.sort(compare));
К сожалению, то, что я получаю в качестве вывода, — это просто массив, отсортированный в алфавитном порядке по имени сотрудника. Кроме того, «заголовок» также включен в сортировку, чего я не хочу, чтобы произошло.
Что я делаю не так, какие-либо советы или альтернативные предложения, кроме использования Array.prototype.sort()
?
Пожалуйста, добрая душа, помоги мне!
Комментарии:
1. Просто, вы можете заставить фрагмент работать ?
2. Привет, спасибо за ваш комментарий и извинения, я не часто использовал функцию сниппета в прошлом. Я внес в него изменения, и вы должны быть в состоянии запустить его сейчас и увидеть результат 🙂
3. нет проблем x) спасибо ! это прекрасно
4. Просто я не понимаю, почему «Профессор Протон» идет за «Бернадетт» (в требуемом выводе), можете ли вы объяснить ?
5. Эй, вообще-то, профессор Протон должен прийти раньше Бернадетт, потому что он ее «менеджер». Фактически, профессор Протон должен быть в верхней части списка (потому что он единственный, кто является «его собственным менеджером» (в списке всегда будет только один уникальный человек, удовлетворяющий этому условию).
Ответ №1:
Вам нужно дерево и получить элементы в глубину-первый обход. Этот (новый подход) работает без изменения полезной нагрузки.
const
sort = array => {
const
t = {},
getManager = data => data[0] === data[1] ? '' : data[1],
getData = manager => (t[manager] || [])
.sort(([a], [b]) => a.localeCompare(b))
.flatMap(data => [data, ...getData(data[0])]);
array.forEach(data => (t[getManager(data)] ??= []).push(data));
return getData('');
},
data = [["Name", "Manager"], ["Leonard", "Penny"], ["Penny", "Professor Proton"], ["Sheldon", "Bernadette"], ["Raj", "Penny"], ["Professor Proton", "Professor Proton"], ["Howard", "Bernadette"], ["Bernadette", "Professor Proton"]],
result = [data[0], ...sort(data.slice(1))];
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Комментарии:
1. Вау, кажется, это работает безупречно! Большое тебе спасибо, Нина! Я действительно понятия не имею, как и почему это работает :D, Следовательно, я даже не могу приспособить это к моей конкретной ситуации (проблема из моего вопроса была упрощена, на самом деле у каждого сотрудника есть больше информации, чем просто их имя и имя их менеджера, например, смена, язык и т. Д.), Но я думаю, что потрачу следующие пару часов на выяснение этого 🙂 Ура!
2. @finaslonchas, извини. пожалуйста, смотрите раздел правка. теперь он принимает данные без их изменения.
Ответ №2:
Тип, который вы описали, в основном представляет собой уплощенную древовидную структуру.
Здесь построение дерева по ссылке в a Map
, перемещение элементов верхнего уровня ( employee
=== manager
) в дерево, затем выравнивание с помощью очереди.
Я расширил набор данных, чтобы включить больше свойств в качестве примера, основанного на вашем комментарии к ответу Нины.
const input = [
['Name', 'Manager', 'Shift', 'Language'],
['Leonard', 'Penny', 'Day', 'en'],
['Penny', 'Professor Proton', 'Day', 'en'],
['Sheldon', 'Bernadette', 'Night', 'en'],
['Raj', 'Penny', 'Night', 'en'],
['Professor Proton', 'Professor Proton', 'Swing', 'en'],
['Howard', 'Bernadette', 'Night', 'en'],
['Bernadette', 'Professor Proton', 'Day', 'en'],
];
const [head, ...temp] = input;
const map = new Map(temp
.sort((a, b) => a[0].localeCompare(b[0]))
.map(([, m]) => [m, []]));
const tree = [];
for (const [n, m, ...rest] of temp) {
const o = { employee: [n, m, ...rest], children: map.get(n) };
if (n === m) {
tree.push(o);
} else {
map.get(m).push(o);
}
}
const res = [head];
while (tree.length) {
const { employee, children } = tree.shift();
res.push(employee);
tree.unshift(...(children ?? []));
}
console.log(res);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Ответ №3:
Я не до конца понимаю вашу цель, потому что ваши ожидаемые результаты и ваши объяснения не совпадают (но, вероятно, я просто этого не вижу). Но вот что я написал, что, по моему мнению, соответствует вашим критериям?
const input = [
['Name', 'Manager'],
['Leonard', 'Penny'],
['Penny', 'Professor Proton'],
['Sheldon', 'Bernadette'],
['Raj', 'Penny'],
['Professor Proton', 'Professor Proton'],
['Howard', 'Bernadette'],
['Bernadette', 'Professor Proton'],
];
const sort = (arr) => {
return arr.map(el => [el[1], el[0]]) //swap employee and manager
.sort() //sort by the first element (i.e. manager)
.map(el => [el[1], el[0]]) //swap back employee and manager
.sort((a,b) => b[0] === b[1] ? 1 : -1 ); //move element to front if employee is the manager
}
console.log(sort(input));
Его результат выглядит следующим образом, который отличается от ваших ожидаемых результатов, но соответствует критериям:
[["Professor Proton", "Professor Proton"],
["Penny", "Professor Proton"],
["Bernadette", "Professor Proton"],
["Raj", "Penny"],
["Leonard", "Penny"],
["Name", "Manager"],
["Sheldon", "Bernadette"],
["Howard", "Bernadette"]]
Комментарии:
1. Эй, спасибо за ваш ответ! В принципе, у меня есть три уровня в иерархии: уровень 1 = профессор Протон, уровень 2 = Бернадетт и Пенни (они подчиняются профессору Протону), уровень 3 = Говард, Леонард, Радж, Шелдон (они подчиняются либо Бернадетт, либо Пенни). Я хочу, чтобы профессор Протон был наверху, а затем ниже Бернадетт, затем Говарда и Шелдона (в алфавитном порядке). Затем я хочу, чтобы появилась Пенни (она идет в алфавитном порядке после Бернадетт, и они находятся на одном уровне), затем Леонард и Радж в алфавитном порядке. Извините, если я был неясен в своем вопросе (был на моем втором косяке).