Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

224
Visualizações
Finding intersection between 2 arrays of objects with dynamic keys

I have 2 arrays of objects with dynamic keys (i never know the name of the key); Example:

hierarchy1: [
  {
    level1: 'Shoes',
  }
]

hierarchy2: [
  {
    level1: 'Shoes',
    level2: 'Sneakers',
  },
]

I need to find intersection between hierarchy1 and hierarchy2. I can't use lodash _.intersectionBy because i dont know the name of the key i will get in hierarchy1.

I'd expect to get the result like this [{ level1: 'Shoes' }] Any ideas how to solve this issue?

Thanks a lot!

about 4 years ago · Juan Pablo Isaza
3 Respostas
Responde à pergunta

0

if you want to compare with every index then you can do something like this

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))

an improvement to first approach is doing some pre-calculations, you can simply club all the values for a particular key and when looping over you can check if there's particular value present for the given key or not

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))

If you just want to compare respective indexes or both array you can do something like this

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))

about 4 years ago · Juan Pablo Isaza Relatório

0

You can use _.intersectionWith() that accepts multiple arrays, and a comparator function to compare between two items. To find matching keys, we can use _.intersection() between the keys of the two objects, and then use Array.some() to find at least one key that have matching values in both objects.

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>

The main caveat using _.intersectionWith() is that as soon as an item matches it's not used again. So if for example you have

const arr1 = [{ level1: 'Shoes' }, { level2: 'Sneakers' }],
const arr2 = [{ level1: 'Shoes', level2: 'Sneakers' }]

only the { level1: 'Shoes' } because { level1: 'Shoes', level2: 'Sneakers' } would not be used to compare with { level2: 'Sneakers' }, since a match was found.

If you want to find all objects with matching keys, you'll need to compare all objects in one array to all objects in the other. To do so, filter the 1st array. Use Array.some() to iterate the 2nd array. Get all unique keys (using a Set), and then try to find at least one key that has the same value in both objects.

Note: without the match once limit, multiple objects from the 1st array can be matched by a single object in the 2nd.

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' }]
))

about 4 years ago · Juan Pablo Isaza Relatório

0

You can use this to reshape it a tad.

var all = [...hierarchy1, ...hierarchy2].map(c=> Object.entries(c)).flat()
/*
[
  [ 'level1', 'Shoes' ],
  [ 'level1', 'Shoes' ],
  [ 'level2', 'Sneakers' ]
]
*/

Then put it into whatever format you want after that

all.reduce((a,[key,value])=>({
     ...a, 
    [key]: a[key]?a[key]+1:1
  }),{})

/*
{ level1: 2, level2: 1 }
*/
about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda