Search code examples
javascriptarrayslodash

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!


Solution

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