Tengo 2 matrices de objetos con claves dinámicas (nunca sé el nombre de la clave); Ejemplo:
hierarchy1: [ { level1: 'Shoes', } ] hierarchy2: [ { level1: 'Shoes', level2: 'Sneakers', }, ]Necesito encontrar la intersección entre la jerarquía1 y la jerarquía2. No puedo usar lodash _.intersectionBy porque no sé el nombre de la clave que obtendré en la jerarquía1 .
Esperaría obtener un resultado como este [{ level1: 'Shoes' }] ¿Alguna idea de cómo resolver este problema?
¡Muchas gracias!
si desea comparar con cada índice, puede hacer algo como esto
const hierarchy1 = [{ level1: 'Shoes', level3: "xyz" }] const hierarchy2 = [{ level1: 'Shoes', level2: 'Sneakers', }, { level3: "xyz" }] function intersection(arr1, arr2) { let final = [] // loop over first array for (let i = 0; i < arr1.length; i++) { let element = arr1[i] let temp = {} // loop over all indexes of second array for (let data of arr2) { // check every key fro data to see if there's any intersection Object.keys(data).forEach(key => { if (data[key] === element[key] && key in element) { temp[key] = element[key] } }) } // if we found any intersection push it in final array if (Object.keys(temp).length) { final.push(temp) } } return final } console.log(intersection(hierarchy1, hierarchy2))una mejora al primer enfoque es hacer algunos cálculos previos, simplemente puede agrupar todos los valores para una clave en particular y al recorrer puede verificar si hay un valor particular presente para la clave dada o no
const hierarchy1 = [{ level1: 'Shoes', level3: "xyz" },{level2: "abc"}] const hierarchy2 = [{ level1: 'Shoes', level2: 'Sneakers', }, { level3: "xyz", level2: "abc" }] function intersection(arr1, arr2) { let final = [] let map = {} for(let data of arr2){ Object.keys(data).forEach(key => { map[key] = map[key] || new Set() map[key].add(data[key]) }) } // loop over first array for (let i = 0; i < arr1.length; i++) { let element = arr1[i] let temp = {} Object.keys(element).forEach(key => { if (key in map && map[key].has(element[key])) { temp[key] = element[key] } }) // if we found any intersection push it in final array if (Object.keys(temp).length) { final.push(temp) } } return final } console.log(intersection(hierarchy1, hierarchy2))Si solo desea comparar los índices respectivos o ambas matrices, puede hacer algo como esto
const hierarchy1 = [{ level1: 'Shoes', }] const hierarchy2 = [{ level1: 'Shoes', level2: 'Sneakers', },] function intersection(arr1,arr2){ let final = [] for(let i=0; i<arr1.length; i++){ let element = arr1[i] let temp = {} Object.keys(element).forEach(key => { if(key in arr2[i] && arr2[i][key] === element[key]){ temp[key] = element[key] } }) if(Object.keys(temp).length){ final.push(temp) } } return final } console.log(intersection(hierarchy1,hierarchy2))Puede usar _.intersectionWith() que acepta múltiples matrices y una función de comparación para comparar entre dos elementos. Para encontrar claves coincidentes, podemos usar _.intersection() entre las claves de los dos objetos y luego usar Array.some() para encontrar al menos una clave que tenga valores coincidentes en ambos objetos.
const intersectionWithDynamicKeys = (arr1, arr2) => _.intersectionWith( arr1, arr2, (o1, o2) => _.union(_.keys(o1), _.keys(o2)) .some(key => o1[key] === o2[key]) ) // Finds [{ level1: 'Shoes' }] console.log(intersectionWithDynamicKeys( [{ level1: 'Shoes' }], [{ level1: 'Shoes', level2: 'Sneakers' }] )) // Finds [{ level1: 'Shoes' }] but doesn't find { level2: 'Sneakers' console.log(intersectionWithDynamicKeys( [{ level1: 'Shoes' }, { level2: 'Sneakers' }], [{ level1: 'Shoes', level2: 'Sneakers' }] )) <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> La advertencia principal al usar _.intersectionWith() es que tan pronto como un elemento coincida, no se volverá a usar. Así que si por ejemplo tienes
const arr1 = [{ level1: 'Shoes' }, { level2: 'Sneakers' }], const arr2 = [{ level1: 'Shoes', level2: 'Sneakers' }] solo { level1: 'Shoes' } porque { level1: 'Shoes', level2: 'Sneakers' } no se usaría para comparar con { level2: 'Sneakers' } , ya que se encontró una coincidencia.
Si desea encontrar todos los objetos con claves coincidentes, deberá comparar todos los objetos en una matriz con todos los objetos en la otra. Para hacerlo, filtre la primera matriz. Use Array.some() para iterar la segunda matriz. Obtenga todas las claves únicas (usando un Set ) y luego intente encontrar al menos una clave que tenga el mismo valor en ambos objetos.
Nota : sin el límite de coincidencia única, múltiples objetos de la primera matriz pueden coincidir con un solo objeto en la segunda.
const getUniqueKeys = (o1, o2) => [...new Set([...Object.keys(o1), ...Object.keys(o2)])] const intersectionWithDynamicKeys = (arr1, arr2) => arr1.filter(o1 => arr2.some(o2 => getUniqueKeys(o1, o2) .some(key => o1[key] === o2[key]) ) ) // Finds [{ level1: 'Shoes' }, { level2: 'Sneakers' }] console.log(intersectionWithDynamicKeys( [{ level1: 'Shoes' }, { level2: 'Sneakers' }], [{ level1: 'Shoes', level2: 'Sneakers' }] )) // Finds [{ level1: 'Shoes' }, { level2: 'Sneakers' }, { level2: 'Sneakers' }] console.log(intersectionWithDynamicKeys( [{ level1: 'Shoes' }, { level2: 'Sneakers' }, { level2: 'Sneakers' }], [{ level1: 'Shoes', level2: 'Sneakers' }] ))Puedes usar esto para remodelarlo un poco.
var all = [...hierarchy1, ...hierarchy2].map(c=> Object.entries(c)).flat() /* [ [ 'level1', 'Shoes' ], [ 'level1', 'Shoes' ], [ 'level2', 'Sneakers' ] ] */Luego póngalo en el formato que desee después de eso
all.reduce((a,[key,value])=>({ ...a, [key]: a[key]?a[key]+1:1 }),{}) /* { level1: 2, level2: 1 } */