数组中对象之间的差异

时间:2016-11-18 11:55:31

标签: javascript reactjs underscore.js

我试图找到复杂数组中元素之间的差异。

我有如下数组列表:

[
    [{
        id: 123,
        list: [{
            name: "Vimal",
            status: "Pass"
        }, {
            name: "Selvam",
            status: "Pass"
        }]
    }],
    [{
        id: 124,
        list: [{
            name: "Vimal",
            status: "Pass"
        }, {
            name: "Selvam",
            status: "Fail"
        }, {
            name: "Raj",
            status: "Pass"
        }]
    }]
]

我希望list之间的区别如下:

[{
    id: 123,
    list: [{
        name: "Selvam",
        status: "Pass"
    }]
}, {
    id: 124,
    list: [{
        name: "Selvam",
        status: "Fail"
    }, {
        name: "Raj",
        status: "Pass"
    }]
}]

我想循环每个元素并与相邻元素进行比较,然后将差异存储到临时变量中。但这听起来太麻烦了。我只是希望你如何改变我看待这个问题的方式。指针会更有帮助。否则,是否有任何库可以轻松解决这个问题?

EDIT1 : 请注意,列表的长度始终不是2.大小是动态的。并且应该在所有元素之间进行比较。

2 个答案:

答案 0 :(得分:1)

如果您想要差异,则需要两个对象的 交叉点

在您的情况下,您需要先了解不同之处。然后你可以使用它来删除属性以了解 对称差异

这是一个非常复杂的问题,因为如果 O(n 2 ,则比较数组。在下面的例子中,我只是比较了JSON值。这对您的问题很方便,但不建议使用更复杂的对象数组。

注意: 我不知道你为什么选择在没有嵌套数组的情况下将对象包装在数组中?我删除了括号以简化逻辑。查看更改的JSON。您可以轻松地将其添加回需要的逻辑中。

var dataArr = getSampleData();
var intersectObj = findObjectIntersection(dataArr[0], dataArr[1], {});

document.body.innerHTML = '<pre>' + JSON.stringify(intersectObj, null, 4) + '</pre>';

// Iterate over all keys and find similar key-values.
function findObjectIntersection(obj1, obj2, obj3) {
  var keys1 = Object.keys(obj1); // Object 1 keys
  var keys2 = Object.keys(obj2); // Object 2 keys
  var keysL = keys1.length > keys2.length ? keys1 : keys2;
  var keysS = keysL === keys1 ? keys2 : keys1;
  var keysD = keysL.filter(function(key) {
    return keysS.indexOf(key) > -1;
  });
  for (var i = 0; i < keysD.length; i++) {
    var currKey = keysD[i];
    var val1 = obj1[currKey];
    var val2 = obj2[currKey];

    if (isValue(val1) && isValue(val2)) {
      if (val1 === val2) {
        obj3[currKey] = val1;
      }
    } else if (isArray(val1) && isArray(val2)) {
      obj3[currKey] = findArrayIntersectionSimple(val1, val2, []);
    }
  }
  return obj3;
}

// Only compare values by JSON.
function findArrayIntersectionSimple(arr1, arr2, arr3) {
  var arrL = arr1.length > arr2.length ? arr1 : arr2;
  var arrS = arrL === arr1 ? arr2 : arr1;
  for (var i = 0; i < arrL.length; i++) {
    for (var j = 0; j < arrS.length; j++) {
      var val1 = JSON.stringify(arrL[i]);
      var val2 = JSON.stringify(arrS[j]);
      if (val1 === val2) {
        arr3.push(arrL[i]);
      }
    }
  }
  return arr3;
}

function isFunction(obj) {
  return {}.toString.apply(obj) === '[object Function]';
}

function isArray(obj) {
  return {}.toString.apply(obj) === '[object Array]';
}

function isObject(obj) {
  return {}.toString.apply(obj) === '[object Object]';
}

function isValue(obj) {
  return !isObject(obj) && !isArray(obj);
}

function getSampleData() {
  return [{
    id: 123,
    list: [{
      name: "Vimal",
      status: "Pass"
    }, {
      name: "Selvam",
      status: "Pass"
    }]
  }, {
    id: 124,
    list: [{
      name: "Vimal",
      status: "Pass"
    }, {
      name: "Selvam",
      status: "Fail"
    }, {
      name: "Raj",
      status: "Pass"
    }]
  }];
}

答案 1 :(得分:0)

Mr. Polywhirl所述,您希望获得两个数组之间的对称差异。

正如它所发生的那样,Lodash具有以下功能:xorWith

这是一个用法示例:

var symmetricDifference = _.xorWith(array1, array2, comparisonFn);

在此示例中,xorWith()正在使用array1函数比较array2comparisonFn的值。

由于数组的值是对象,因此您需要使用深度检查对象是否相等的比较函数。 Lodash只有这样的比较功能:isEqual

因此,对于您的使用案例,您可能会使用以下代码获得两个列表之间的对称差异(让我们称之为list1list2):

var symmetricDifference = _.xorWith(list1, list2, _.isEqual);