首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >用动态键查找两个对象数组之间的交集

用动态键查找两个对象数组之间的交集
EN

Stack Overflow用户
提问于 2022-06-09 17:34:19
回答 3查看 344关注 0票数 0

我有两个带有动态键的对象数组(我永远不知道键的名称);例如:

代码语言:javascript
运行
复制
hierarchy1: [
  {
    level1: 'Shoes',
  }
]

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

我需要找到hierarchy1和hierarchy2之间的交叉点。我不能使用_.intersectionBy,因为我不知道我将在hierarchy1中得到的密钥的名称。

我希望得到这样的结果{ level1:‘鞋子’}有什么想法如何解决这个问题?

非常感谢!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2022-06-09 17:53:21

如果您想要与每个索引进行比较,那么您可以这样做

代码语言:javascript
运行
复制
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))

对第一种方法的改进是做一些预计算,您可以简单地将特定键的所有值合并起来,当循环结束时,您可以检查给定键是否存在特定值。

代码语言:javascript
运行
复制
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))

如果您只想比较各自的索引或这两个数组,您可以这样做

代码语言:javascript
运行
复制
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))

票数 0
EN

Stack Overflow用户

发布于 2022-06-09 21:05:29

您可以使用接受多个数组的_.intersectionWith()和一个比较器函数来比较两个项。要查找匹配的键,可以在两个对象的键之间使用_.intersection(),然后使用Array.some()查找至少一个在两个对象中具有匹配值的键。

代码语言:javascript
运行
复制
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' }]
))
代码语言:javascript
运行
复制
<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>

使用_.intersectionWith()的主要警告是,一旦一个项目匹配,就不会再次使用它。所以,例如,如果你

代码语言:javascript
运行
复制
const arr1 = [{ level1: 'Shoes' }, { level2: 'Sneakers' }],
const arr2 = [{ level1: 'Shoes', level2: 'Sneakers' }]

只有{ level1: 'Shoes' },因为由于找到了匹配项,所以不会使用{ level1: 'Shoes', level2: 'Sneakers' }{ level2: 'Sneakers' }进行比较。

如果要查找所有具有匹配键的对象,则需要将一个数组中的所有对象与另一个数组中的所有对象进行比较。为此,过滤第一个数组。使用Array.some()迭代第二个数组。获取所有唯一键(使用Set),然后尝试找到至少一个在两个对象中具有相同值的键。

备注:在没有匹配一次限制的情况下,第一个数组中的多个对象可以由第二个数组中的单个对象匹配。

代码语言:javascript
运行
复制
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' }]
))

票数 0
EN

Stack Overflow用户

发布于 2022-06-09 22:02:10

你可以用这个来重塑它一点。

代码语言:javascript
运行
复制
var all = [...hierarchy1, ...hierarchy2].map(c=> Object.entries(c)).flat()
/*
[
  [ 'level1', 'Shoes' ],
  [ 'level1', 'Shoes' ],
  [ 'level2', 'Sneakers' ]
]
*/

然后把它放进你想要的任何格式。

代码语言:javascript
运行
复制
all.reduce((a,[key,value])=>({
     ...a, 
    [key]: a[key]?a[key]+1:1
  }),{})

/*
{ level1: 2, level2: 1 }
*/
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72564437

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档