javascript - 在嵌套对象中查找相似之处
问题描述
假设我有:
const a = {
'prkn': {
tec: [ 'Coding', 'Machine Learning', 'Cloud Development' ],
des: [ 'Web Design' ]
},
'pekn': { cu: [ 'Musica', 'Cinema', 'Arte' ] }
}
const b = {
'prkn': {
tec: [
'Coding',
'Machine Learning',
'Cloud Development',
'IoT Management'
],
des: [ 'UX/UI', 'Web Design', 'Prototyping', 'Design Thinking' ]
},
'pekn': { cu: [ 'Cinema', 'Lettura' ] }
}
我想要这些对象的交集:
{
'prkn': {
tec: [ 'Coding', 'Machine Learning', 'Cloud Development' ],
des: [ 'Web Design' ]
},
'pekn': { cu: [ 'Cinema' ] }
}
这是代码,但它不起作用..:
const a = {
'prkn': {
tec: [ 'Coding', 'Machine Learning', 'Cloud Development' ],
des: [ 'Web Design' ]
},
'pekn': { cu: [ 'Musica', 'Cinema', 'Arte' ] }
}
const b = {
'prkn': {
tec: [
'Coding',
'Machine Learning',
'Cloud Development',
'IoT Management'
],
des: [ 'UX/UI', 'Web Design', 'Prototyping', 'Design Thinking' ]
},
'pekn': { cu: [ 'Cinema', 'Lettura' ] }
}
function findSimilarities(obj1, obj2) {
const bo1 = Object.entries(obj1).reduce((acc1, [l1, v1]) => {
const bo2 = Object.entries(v1).reduce((acc2, [l2, v2]) => {
const sim = v2.filter(s => obj2[l1][l2].includes(s))
acc2[l2] = sim
return acc2
})
acc1[l1] = bo2
return acc1
}, {})
return bo1
}
console.log(findSimilarities(a, b))
解决方案
这是一个相当简单的示例,适用于您的给定数据。
它首先与Object.keys()
传递的对象相交并根据typeof
它们关联的属性过滤它们,这样我们就不会浪费时间比较未共享的键或类型不匹配的键。然后它遍历这些键,如果它们引用它递归的对象(但不是数组),否则如果两者都是数组与它们相交(这里使用includes()
嵌套对象将不起作用),最后检查基本相等性。设置acc[key]
并返回。
const
a = { 'prkn': { red: 1, bl: null, tec: ['Coding', 'Machine Learning', 'Cloud Development'], des: ['Web Design'] }, 'pekn': { cu: ['Musica', 'Cinema', 'Arte'] } },
b = { 'prkn': { red: 1, bl: 'Dog', tec: ['Coding', 'Machine Learning', 'Cloud Development', 'IoT Management'], des: ['UX/UI', 'Web Design', 'Prototyping', 'Design Thinking'] }, 'pekn': { cu: ['Cinema', 'Lettura'] } },
intersectPrimitiveArrays = (a, b) => a.filter(e => b.includes(e)),
intersectObjects = (a, b) => {
const keys = intersectPrimitiveArrays(Object.keys(a), Object.keys(b))
.filter(k => (typeof a[k]) === (typeof b[k]));
return keys.reduce((acc, key) => {
const
_a = a[key],
_b = b[key];
let element = _a;
if (typeof _a === 'object' && (_a !== null || _b !== null) && (!Array.isArray(_a) && !Array.isArray(_b))) {
element = intersectObjects(_a, _b);
} else if (Array.isArray(_a) && Array.isArray(_b)) {
element = intersectPrimitiveArrays(_a, _b);
} else if (_a !== _b) {
element = undefined;
}
if (element !== undefined) {
acc[key] = element;
}
return acc;
}, {})
}
console.log(intersectObjects(a, b));
.as-console-wrapper { max-height: 100% !important; top: 0; }
推荐阅读
- php - Drupal 8:我们可以在自定义模块中使用具有自己模板的多个块吗?
- c# - 重定向不重定向到指定的操作
- javascript - 在 Chart.js 中为一个数据集中的单个点设置样式
- symfony - Symfony - Form - IntegerType 接受 1.00 (x.00) 值作为有效值
- encryption - 如何确保我发送了加密消息?
- python - 为什么 pytest 不运行作为参数传递给测试函数的 conftest.py 函数?
- .net - 具有特定区域和缩放功能的可缩放墨卡托 SVG 像素转换器 (VB.NET)
- python - 使用 ipyvuetify 突出显示文本
- docker - 无法在 localhost 上加载 Docker 容器
- multithreading - 同一个线程在切换到另一个内核后会看到最新的值吗?