2015-12-21 3 views
15

У меня есть два объекта литералов, как так:Лучший способ получить пересечение ключей двух объектов?

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

Lodash имеет [пересечение] (https://lodash.com/docs#intersection) как метод, если вы не были уже осведомлены , – Xotic750

+0

@ Xotic750 Кажется, работает только с массивами? Опять же, существует много способов, как 'Object.keys' получить ключи в виде массива. – Piwwoli

+3

Конечно, вам понадобятся ключи каждого объекта, как в ответах ниже, либо ['Object.keys'] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/ Global_Objects/Object/keys) или lodash имеет ['_.keys'] (https://lodash.com/docs#keys). '_.intersection (_. keys (firstObject), _.keys (secondObject));' – Xotic750

ответ

19

Раствор без 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>');

Вторая попытка с O (N).

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).filter({}.hasOwnProperty.bind(o2)); 
 
} 
 

 
document.write('<pre>' + JSON.stringify(intersection(firstObject, secondObject), 0, 4) + '</pre>');

+0

У меня сложилось впечатление, что объекты js всегда сортируются по ключевым словам ... –

+1

@AmitKriplani не гарантируется вообще в ES5 и гарантированно будет в порядке создания в ES2015 – zerkms

+2

@NinaScholz: это хороший ответ. Было бы даже красивее, если бы 'сокращение' было чистым (не использовал свободный« результат ») PS: OP не заботится о равенстве значений - это просто пересечение имен ключей – zerkms

4

Процедура я предлагаю это:

  1. Получить array ключей с помощью Object.keys() для одного из объектов.
  2. Найдите пересечение массива с помощью .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));

+0

Мне, наверное, интересно то же самое, как это имеет значение, если вы делаете 'k1.filter' или' k2.filter' в любом случае ? – Piwwoli

+0

@HunanRostomyan Я не верю, что он может быть ложным, так как первое значение в функции обратного вызова фильтра возвращает текущее значение фильтруемого массива.В этом случае k1 фильтруется, делая первую проверку избыточной, так как мы знаем, что значение должно существовать, поскольку оно передается через обратный вызов. –

+1

@Piwwoli Не имеет значения, пересечение (A и B) и (B и A) является одним и тем же множеством, поэтому вы можете начать с каждого члена A и проверить, находится ли он также в B, * или * начинаться с каждого член B и проверьте, находится ли он в A. Что я предлагаю с моим вопросом, так это то, что вам не нужно проверять два членства, потому что элемент ('x') уже выбран из одного из этих наборов (@Monica просто объяснил то же самое). –

7

данные ответы красиво и удивительно, но там может быть проблема в void «s answer и что:. " Что делать, если один из значений свойств намеренно установлен в undefined "

Ninaanswer является хорошим (действительно фантастическим), но поскольку мы находимся на грани завтрашнего дня JavaS cript Я думаю, что мое обыкновение быть слишком плохо:

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

Смежные вопросы