Tengo una serie de cadenas que se pueden ver como una plantilla/referencia:
// Template let template = ['A', 'B', 'C'];También tengo una matriz de objetos que contienen algunas de las cadenas de la matriz:
// Source (to be sorted) let source = [ { items: ['B', 'D', 'E'] }, { items: ['E', 'L', 'Y'] }, { items: ['G', 'B', 'A'] }, { items: ['C', 'B', 'A'] } ]; Ahora necesito encontrar una manera de ordenar los items en la matriz de source haciendo coincidir la matriz de template (de mejor a peor). El orden de las cadenas en los items es irrelevante.
Según mi ejemplo anterior, el resultado después de ordenar se vería así:
// Result after sorting let sorted = [ { items: ['C', 'B', 'A'] }, // 3 matches (A, B, C) { items: ['G', 'B', 'A'] }, // 2 matches (A, B) { items: ['B', 'D', 'E'] }, // 1 match (B) { items: ['E', 'L', 'Y'] } // no match ];Con el método de JavaScript .sort() y .localCompare() puedo ordenar una matriz basada en cadenas, pero no pude encontrar una manera de ordenar por una 'plantilla' de matriz dada.
Estaría más que feliz si alguien sabe cómo hacerlo. ¡Gracias de antemano!
Puede basar su lógica en el tamaño del Set que contiene elementos distintos tanto de la template como de los items . Cuanto más pequeño es el Set , más elementos comunes:
const template = ['A', 'B', 'C']; const source = [ { items: ['B', 'D', 'E'] }, { items: ['E', 'L', 'Y'] }, { items: ['G', 'B', 'A'] }, { items: ['C', 'B', 'A'] } ]; const target = source .map(({items}) => ({items, size: new Set([...items, ...template]).size})) .sort((a, b) => a.size - b.size); console.log(target);En caso de que no esté tratando con valores distintos en sus matrices, esto podría ser más apropiado:
const template = ['A', 'B', 'C']; const source = [ { items: ['B', 'D', 'E'] }, { items: ['E', 'L', 'Y'] }, { items: ['G', 'B', 'A'] }, { items: ['C', 'B', 'A'] } ]; const target = source .map(({items}) => ({ items, size: items.reduce((a, v) => a + template.includes(v), 0) })) .sort((a, b) => b.size - a.size); console.log(target); Esto se puede optimizar aún más convirtiendo la template en un Set .
Simplemente necesita crear una función de clasificación adecuada que compare 2 elementos de matriz. Por ejemplo, puede contar los elementos que coinciden con su plantilla.
function sortByMatch(template) { const items = new Set(template) const rank = arr => arr.filter(item => items.has(item)).length return (a, b) => rank(b.items) - rank(a.items) } let template = ['A', 'B', 'C']; let source = [ { items: ['B', 'D', 'E'] }, { items: ['E', 'L', 'Y'] }, { items: ['G', 'B', 'A'] }, { items: ['C', 'B', 'A'] } ]; const sorted = source.slice().sort(sortByMatch(template)) console.log(sorted.map(item => item.items.join(', ')))