Digamos que tiene dos matrices y desea encontrar el grupo más visitado (o grupos; se le dará un límite) de:
const Animals = [ { id: 1, name: "cat", group: "four legs"}, { id: 2, name: "dog", group: "four legs"}, { id: 3, name: "bird", group: "two legs"}, { id: 4, name: "fish", group: "no legs"}, { id: 5, name: "ants", group: "six legs"}, { id: 6, name: "monkey", group: "two legs"}, { id: 7, name: "horse", group: "four legs"}, { id: 8, name: "spiders", group: "eight legs"}, { id: 9, name: "catepillar", group: "many legs"}, { id: 666, name: "unused", group: "unused"}, ] const AnimalVisits= [ { id: 1, visits: 40 }, { id: 2, visits: 30 }, { id: 3, visits: 50 }, { id: 4, visits: 100 }, { id: 5, visits: 90 }, { id: 6, visits: 110 }, { id: 7, visits: 20 }, { id: 8, visits: 160 }, { id: 9, visits: 1000 }, { id: 10, visits: 2000},//not in list!! ]Respuesta esperada "muchas piernas" para el top 1.
He escrito mi propia solución, pero no estoy convencido de que sea la más eficiente, ya que es muy larga y sería difícil de mantener, además la principal preocupación es la eficiencia del tiempo de ejecución.
No utilicé bibliotecas/ayudantes, solo JS puro. Mis pasos fueron:
Diría que puede haber soluciones más rápidas para este problema, pero depende de lo que esté involucrado en los pasos que describió. Específicamente, el primer paso que mencionas:
"Cree una nueva matriz con "grupo" de Animal y AnimalVisits".
Debido a que las matrices de visitas y animales en su OP ya están ordenadas por ID, esto podría lograrse en tiempo lineal, sin embargo, si eso no siempre va a ser un hecho para el problema, las implementaciones pueden variar enormemente. Por ejemplo, ¿está recorriendo todo el conjunto de animales cada vez para encontrar la identificación superpuesta?
Continuando, el paso "agregar por grupo" también se puede lograr en tiempo lineal al leer cada elemento en un mapa, pero no menciona un mapa, por lo que nuevamente la complejidad del tiempo puede variar según la implementación; nuevamente, como el paso 1, el más costoso La forma de agregar tiempo a este método sería hacer un bucle en la matriz a medida que agrega.
En mi opinión, cualquier enfoque eficiente para este problema implicará un mapa / tabla hash, etc. A continuación, publiqué una solución semieficiente para el problema, pero tenga en cuenta * este problema tiene mucho en común con encontrar el K-ésimo elemento más grande en una lista problema, y la solución más eficiente utiliza una cola de prioridad para mantener los elementos en orden. Javascript no admite de forma nativa una cola de prioridad, pero ahí es donde iría para acelerar esto; parece que ya hay al menos 1 paquete en NPM (descargo de responsabilidad: no lo he usado). Tal como están las cosas, simplemente clasifico la salida y luego elimino los últimos N elementos para cumplir con su requisito de límite.
function mostVisits(animals, visits, topN) { const groups = new Map(); const animalLookup = new Map(); for (let i = 0; i < animals.length; i++) { animalLookup.set(animals[i].id, animals[i]) } for (let j = 0; j < visits.length; j++) { console.log(visits[j], animalLookup.get(visits[j].id)) const group = animalLookup.get(visits[j].id).group; if (!groups.has(group)) groups.set(group, visits[j].visits); else groups.set(group, groups.get(group) + visits[j].visits); } return Array.from(groups).sort((a, b) => a[1] - b[1]).slice(-1 * topN); }Aquí hay casi la misma solución que muestra cómo podría aprovechar el hecho de que las entradas ya están ordenadas:
function mostVisits(animals, visits, topN) { const groups = new Map(); for (let i = 0; i < animals.length; i++) { const group = animals[i].group; if (!groups.has(group)) groups.set(group, visits[i].visits); else groups.set(group, groups.get(group) + visits[i].visits); } return Array.from(groups).sort((a, b) => a[1] - b[1]).slice(-1 * topN); }Nota * si tuviera que usar una cola de prioridad para acelerar las cosas, reemplazaría la última línea de mi función allí, es decir. Array.from().sort().slice()
¡Espero que esto ayude!
Hago una función con un enfoque de clasificación por el método Array.sort() en orden descendente (de arriba a abajo) , seguido de cortar la matriz por cuántos límites desea, luego mapearla con la matriz de animals y obtener solo el grupo de propiedades que desee, finalmente join de nuevo con la coma ', ' .
const animals = [ { id: 1, name: "cat", group: "four legs" }, { id: 2, name: "dog", group: "four legs" }, { id: 3, name: "bird", group: "two legs" }, { id: 4, name: "fish", group: "no legs" }, { id: 5, name: "ants", group: "six legs" }, { id: 6, name: "monkey", group: "two legs" }, { id: 7, name: "horse", group: "four legs" }, { id: 8, name: "spiders", group: "eight legs" }, { id: 9, name: "catepillar", group: "many legs" }, ]; const animalsVisits = [ { id: 1, visits: 40 }, { id: 2, visits: 30 }, { id: 3, visits: 50 }, { id: 4, visits: 100 }, { id: 5, visits: 90 }, { id: 6, visits: 110 }, { id: 7, visits: 20 }, { id: 8, visits: 165 }, { id: 9, visits: 1000 }, ]; const topVisited = (limit) => animalsVisits .slice() //shallow copy .sort((a, b) => b.visits - a.visits) //sorting in desending order .slice(0, limit) // cut how many top limit .map(({ id }) => animals.find((animal) => animal.id === id).group) //mapped with group from animals array .join(", ");Pruebas:
console.log(topVisited(1) === "many legs"); //true console.log(topVisited(2) === "many legs, eight legs");//true console.log(topVisited(3) === "many legs, eight legs, two legs");//true Nota: hacer un método Array.sort() cambiaría la matriz original, es por eso que usé Array.slice() para hacer una copia.
Consejo: En cuanto a la denominación de variables, si se trata de una matriz, es preferible nombrarla en plural en lugar de Animal do animals .
Puede hacer un diccionario con el grupo como claves y recorrer la matriz de visitas y seguir agregando valor al grupo. Esto maneja la agregación de múltiples entradas para el mismo grupo.
Luego use Object.entries() para convertirlo en una matriz de [key, value] y sort según el valor.
Finalmente, use Array.prototype.slice() para obtener el rango de valores que necesita.
const Animal= [ { id: 1, name: "cat", group: "four legs"}, { id: 2, name: "dog", group: "four legs"}, { id: 3, name: "bird", group: "two legs"}, { id: 4, name: "fish", group: "no legs"}, { id: 5, name: "ants", group: "six legs"}, { id: 6, name: "monkey", group: "two legs"}, { id: 7, name: "horse", group: "four legs"}, { id: 8, name: "spiders", group: "eight legs"}, { id: 9, name: "catepillar", group: "many legs"}, ] const AnimalVisits= [ { id: 1, visits: 40 }, { id: 2, visits: 30 }, { id: 3, visits: 50 }, { id: 4, visits: 100 }, { id: 5, visits: 90 }, { id: 6, visits: 110 }, { id: 7, visits: 20 }, { id: 8, visits: 165 }, { id: 9, visits: 1000 }, ] const visitDict = Animal.reduce((dict, animal) => { dict[animal.group] ||= 0; dict[animal.group] += AnimalVisits.find(obj => obj.id === animal.id).visits || 0; return dict }, {}) console.log('Dictionary: ', visitDict) const sortedArray = Object.entries(visitDict).sort((a, b) => b[1] - a[1]) console.log('Sorted: ', sortedArray) const sortedGroups = sortedArray.map(arr => arr[0]) // Can be chained after the sort above console.log('Sorted Groups: ', sortedGroups) const getTop = (num) => sortedGroups .slice(0, num) .join(', ') console.log('Top 3: ' + getTop(3))