2

I am trying to find the difference between the elements in the complex array.

I have array list as follows:

[
    [{
        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"
        }]
    }]
]

I would like to get the difference between the list as follows:

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

I was thinking to loop each element and compare with the adjacent element, then store the differences into the temporary variable. But that sounds too cumbersome approach. I just wanted your opinion on how do I change my way of looking this problem. Pointers would be more helpful. Otherwise, is there any library which could solve this problem easily?

Edit1: Please note that the list will always not a length of 2. The size is dynamic. And the comparison should happen between all elements.

Vimalraj Selvam
  • 2,155
  • 3
  • 23
  • 52

2 Answers2

1

If you want the difference you will need the intersection of the two objects.

In your case, you need to know what is different first. Then you can take that and use it to remove properties to know the symmetric difference.

This is a very complex problem, because comparing arrays if an O(n2). In my case below, I just compared the JSON values. Which is convenient for your problem, but it is not advised for a more complicated object array.

Note: I don't know why you chose to wrap your objects inside the array without a nested array? I removed the brackets to simplify the logic. See the changed JSON. You can easily add this back into the logic of need be.

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"
    }]
  }];
}
Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132
  • I guess I didn't communicate properly. You assumed that the list will always be length of 2. But in my case the length will be dynamic. – Vimalraj Selvam Nov 18 '16 at 13:46
0

As Mr. Polywhirl says, you want to get the symmetric difference between two arrays.

As it so happens, Lodash has a utility function for that: xorWith.

Here's a usage example:

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

In this example, xorWith() is comparing the values of array1 and array2 using the comparisonFn function.

Since the values of your arrays are objects, you'll need to use a comparison function that deeply checks objects for equality. Lodash has just such a comparison function: isEqual.

So, for your use case, you may get the symmetric difference between your two lists (let's call them list1 and list2) with something like this code:

var symmetricDifference = _.xorWith(list1, list2, _.isEqual);
Community
  • 1
  • 1
chrismendis
  • 81
  • 1
  • 2