获得两个对象的交叉点的最佳方法是什么?

Piw*_*oli 27 javascript big-o functional-programming intersection object

我有两个对象文字,如下:

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
}
Run Code Online (Sandbox Code Playgroud)

我想获得这两个对象文字的键的交集:

var intersectionKeys  = ['x', 'y', 'z', 'a']
Run Code Online (Sandbox Code Playgroud)

我显然可以做一个循环,看看另一个对象中是否存在具有相同名称的键,但我想知道这对于某些函数式编程和map/filter/reduce用法是否是一个好例子?我自己还没有完成那么多函数式编程,但我有一种感觉,对于这个问题可能存在一个干净而聪明的解决方案.

Nin*_*olz 29

没有的解决方案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>');
Run Code Online (Sandbox Code Playgroud)

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>');
Run Code Online (Sandbox Code Playgroud)

  • @AmitKriplani在ES5中完全没有保证,并且保证在ES2015中处于创建顺序 (2认同)
  • @NinaScholz:这是一个很好的答案.如果`reduce`是纯粹的(没有使用免费的`结果`),它会更漂亮PS:OP不关心值的相等 - 它只是一个关键名称的交集 (2认同)
  • @zerkms,现在好些吗? (2认同)
  • @zerkms大概是NlogN用于排序(不是?).其余的,减少部分增加的复杂性呢? (2认同)

Mor*_*ani 18

给出的答案是好的,惊人但有可能是一个问题无效答案,那就是:' 如果有什么属性值的一个故意设置为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>');
Run Code Online (Sandbox Code Playgroud)


更新

onalbi在评论中提到了一些合理的性能问题,因此下面的代码似乎是处理问题的更好方法:

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

  const [k1, k2] = [Object.keys(o1), Object.keys(o2)];
  const [first, next] = k1.length > k2.length ? [k2, o1] : [k1, o2];
  return first.filter(k => k in next);
}

document.write('<pre>' + JSON.stringify(intersect(a, b)) + '</pre>');
Run Code Online (Sandbox Code Playgroud)


voi*_*oid 7

我建议的程序是:

  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));
Run Code Online (Sandbox Code Playgroud)