Лучший способ получить пересечение ключей двух объектов?
У меня есть два объектных литерала:
var firstObject =
{
x: 0,
y: 1,
z: 2,
a: 10,
b: 20,
e: 30
}
var secondObject =
{
x: 0,
y: 1,
z: 2,
a: 10,
c: 20,
d: 30
}
Я хочу получить пересечение ключей, эти два объектных литерала имеют следующий вид:
var intersectionKeys = ['x', 'y', 'z', 'a']
Я, очевидно, могу сделать цикл и посмотреть, существует ли ключ с тем же именем в другом объекте, но мне интересно, будет ли это хорошим примером для некоторого функционального программирования и использования карты/фильтра/сокращения? Я сам не так много программировал, но у меня есть ощущение, что для этой проблемы может быть чистое и умное решение.
Ответы
Ответ 1
Решение без indexOf
.
var firstObject = { x: 0, y: 1, z: 2, a: 10, b: 20, e: 30 },
secondObject = { x: 0, y: 1, z: 2, a: 10, c: 20, d: 30 };
function intersection(o1, o2) {
return Object.keys(o1).concat(Object.keys(o2)).sort().reduce(function (r, a, i, aa) {
if (i && aa[i - 1] === a) {
r.push(a);
}
return r;
}, []);
}
document.write('<pre>' + JSON.stringify(intersection(firstObject, secondObject), 0, 4) + '</pre>');
Ответ 2
Данные ответы хороши и удивительны, но в пустом ответе может быть проблема: "Что если одно из значений свойства намеренно установлено в undefined
".
Нина ответит хорошо (действительно фантастически), но, поскольку мы находимся на пороге завтрашнего дня в JavaScript, я думаю, что мой не будет слишком плох:
var a = { x: undefined, y: 1, z: 2, a: 10, b: 20, e: 30 }
var b = { x: 0, y: 1, z: 2, a: 10, c: 20, d: 30 }
function intersect(o1, o2){
return Object.keys(o1).filter(k => k in o2)
}
document.write('<pre>' + JSON.stringify(intersect(a, b)) + '</pre>');
Ответ 3
Процедура, которую я предлагаю:
- Получить
array
ключей, используя Object.keys()
для одного из объектов.
- Найти пересечение массива с помощью
.filter
и проверить, содержит ли второй объект ключ, соответствующий первому массиву.
var firstObject = {
x: 0,
y: 1,
z: 2,
a: 10,
b: 20,
e: 30
}
var secondObject = {
x: 0,
y: 1,
z: 2,
a: 10,
c: 20,
d: 30
}
function getIntKeys(obj1, obj2){
var k1 = Object.keys(obj1);
return k1.filter(function(x){
return obj2[x] !== undefined;
});
}
alert(getIntKeys(firstObject, secondObject));
Ответ 4
Рекурсивная функция
Это другое решение, может быть, вам поможет. Я использовал рекурсивную функцию для перехвата двух объектов. Преимущество этого решения заключается в том, что вам не нужно беспокоиться об атрибутах, которые являются объектами одновременно.
В этом случае функция перехватывает атрибуты, которые существуют в обоих объектах, и присваивает значение objSource как окончательное значение атрибута.
{
function interceptObjects(objSource, objInterface) {
let newObj = {};
for (const key in objSource) {
if (objInterface.hasOwnProperty(key)) {
// in javascript an array is a object too.
if (objSource[key] instanceof Object && !Array.isArray(objSource[key]) && objInterface[key] instanceof Object && !Array.isArray(objInterface[key])) {
newObj[key] = {};
newObj[key] = interceptObjects(objSource[key], objInterface[key])
} else {
newObj[key] = objSource[key];
}
}
}
return newObj;
}
// FOR TESTING
let objSource = {
attr1: '',
attr2: 2,
attr3: [],
attr4: {
attr41: 'lol',
attr42: 12,
attr43: 15,
attr45: [1, 4],
},
attr5: [2, 3, 4],
};
let objInterface = {
attr1: null,
attr4: {
attr41: null,
attr42: 12,
attr45: [1],
},
attr5: [],
attr6: null,
};
console.log(this.interceptObjects(objSource, objInterface));
}