Tengo una matriz 2D cuyas entradas representan a un empleado, incluido el nombre de su gerente, algo así:
var array = [["Name", "Manager"], ["Leonard", "Penny"], ["Penny", "Professor Proton"], ["Sheldon", "Bernadette"], ["Raj", "Penny"], ["Professor Proton", "Professor Proton"], ["Howard", "Bernadette"], ["Bernadette", "Professor Proton"]]Si el empleado y el gerente son el mismo, significa que la persona es la más alta en la jerarquía. Lo que quiero lograr es ordenar alfabéticamente a cada empleado debajo de su gerente. En otras palabras, la salida que quiero es esta:
[["Name", "Manager"], ["Professor Proton", "Professor Proton"], ["Bernadette", "Professor Proton"], ["Howard", "Bernadette"], ["Sheldon", "Bernadette"], ["Penny", "Professor Proton"], ["Leonard", "Penny"], ["Raj", "Penny"]] Mi intento fue usar array.sort(compare) con la siguiente función "comparar":
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));Desafortunadamente, lo que obtengo como salida es solo una matriz ordenada alfabéticamente por el nombre del empleado. Además, el "encabezado" también está incluido en la clasificación, lo que no quiero que suceda.
¿Qué estoy haciendo mal, algún consejo o sugerencia alternativa que no sea usar Array.prototype.sort() ?
¡Por favor, alma bondadosa, ayúdame!
Necesita un árbol y obtener los elementos en profundidad primero transversal. Este (nuevo enfoque) funciona sin cambiar la carga útil.
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; }El tipo que ha descrito es básicamente una estructura de árbol aplanado.
Aquí se construye el árbol por referencia en un Map , se empujan los elementos de nivel superior ( employee === manager ) al árbol y luego se aplana usando una cola.
Expandí el conjunto de datos para incluir más propiedades como ejemplo basado en su comentario sobre la respuesta de Nina.
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; }No entiendo completamente su objetivo porque sus resultados esperados y su explicación no se alinean (pero probablemente sea solo que no lo veo). Pero aquí hay algo que escribí que siento que cumple con sus criterios.
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 (ie 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));Su resultado es el siguiente, que es diferente a los resultados esperados pero cumple con los criterios:
[["Professor Proton", "Professor Proton"], ["Penny", "Professor Proton"], ["Bernadette", "Professor Proton"], ["Raj", "Penny"], ["Leonard", "Penny"], ["Name", "Manager"], ["Sheldon", "Bernadette"], ["Howard", "Bernadette"]]