4

I have to compare two unsorted arrays of objects, for example the following code should return true:

compareObjs(
    [{ foo: 'foo', bar: 'bar' }, { baz: 'baz' }], 
    [{ baz: 'baz' }, { foo: 'foo', bar: 'bar' }]
)

I know there are already plenty of answers about comparing arrays of objects, but I did not really find the clear one for comparing the unsorted version of arrays.

7
  • 2
    function compareObjs() { return true } will do that. Why do you expect it to return true, and when should it not? Commented Dec 1, 2017 at 8:23
  • 1
    I expect it to be true because the length of both arrays are the same and they contain the same objects (same keys and values). Object references do not matter in this case. Commented Dec 1, 2017 at 8:24
  • Several questions on here asks the same. Check out: stackoverflow.com/questions/9191791/… and stackoverflow.com/questions/201183/… Commented Dec 1, 2017 at 8:26
  • 1
    @Shota Could you just sort them? Commented Dec 1, 2017 at 8:28
  • I've read that answers, but JSON.stringify won't work, as the arrays are not sorted and I cant use lodash, I have to do this in Vanilla JS Commented Dec 1, 2017 at 8:28

6 Answers 6

2

Here another possibility:

const array2 = [1,3,2,4,5];

const isInArray1 = array1.every(item => array2.find(item2 => item===item2))
const isInArray2 = array2.every(item => array1.find(item2 => item===item2))

const isSameArray = array1.length === array2.length && isInArray1 && isInArray2

console.log(isSameArray); //true
Sign up to request clarification or add additional context in comments.

1 Comment

This doesn't work for objects, and could be improved for primitive types by using .includes() in place of the .find()
0

function givemeSanitizedObject(arr1) {
  let obj = {}
  arr1.forEach(function(element, index, array) {
      obj = {
        ...obj,
        ...element,
      }
  })
  return obj
 }

 function compareObjs(arr1, arr2) {
    let obj1 = givemeSanitizedObject(arr1)
    let obj2 = givemeSanitizedObject(arr2)

    for (var property in obj1) {
      if (Object.hasOwnProperty(property)) {
        if (obj1.property !== obj2.property) {
          return false
        }
      }
    }
    return true
}

console.log(compareObjs(
  [{
    foo: 'foo',
    bar: 'bar'
  }, {
    baz: 'baz'
  }], [{
    baz: 'baz'
  }, {
    foo: 'foo',
    bar: 'bar'
  }]
))

3 Comments

Unfortunately, this doesn't work: you're not keeping the structure of each object. Have a look here, it's your code with two clearly different arrays: jsfiddle.net/1myf4cvk
Yes i think he has a different use case . i saw it now.
You'll want to use reduce instead of forEach in giveMeSanitisedObject. And you need to use [property] instead of .property.
0

You could convert each object to string using JSON.stringify(). Then sort these arrays. And compare each pair.

If you dont't mind about es6:

let arr1 = [{ foo: 'foo', bar: 'bar' }, { baz: 'baz' }];
let arr2 = [{ baz: 'baz' }, { foo: 'foo', bar: 'bar' }];

const Compare = (arr1, arr2) => {
  if (arr1.length != arr2.length) {
    return false
  }

  let a1 = arr1.map(e => JSON.stringify(e)).sort()
  let a2 = arr2.map(e => JSON.stringify(e)).sort()
  
  return !a1.map((e, i) => e == a2[i]).includes(false)
}

console.log(Compare(arr1, arr2))

Comments

0

A basic approach will be to loop through all the objects of one of the arrays and see if you can find similar objects in the other array.

Here is an example:

function compareArrays(arr1, arr2){
    if(arr1.length != arr2.length){
        return false;
    }

    for(var i = 0; i < arr1.length; i++){
        var value1 = arr1[i];
        var keys1 = Object.keys(value1);
        var found = false;
        for(var j = 0; j < arr2.length; j++){
           var value2 = arr2[j];
           var keys2 = Object.keys(value2);
           if(keys1.length == keys2.length 
              && keys1.every(k => keys2.includes(k)) 
              && keys1.every(k => value1[k] == value2[k])){
              found = true;
              break;
           }
        }
        if(!found){
           return false;
        }
    }
   
    return true;
}

var comp = compareArrays(
    [{ foo: 'foo', bar: 'bar' }, { baz: 'baz'}], 
    [{ baz: 'baz' }, { foo: 'foo', bar: 'bar'}]
);

console.log(comp);

Comments

0

You could use a hash table and check if the proprties and values are the same. It works with the given types.

function compareArrays(array1, array2) {
    var hash = {};

    if (array1.length !== array2.length) {
        return false;
    }

    array1.forEach(function (o) {
        var keys = Object.keys(o).sort(),
            key = keys.join('|'),
            value = keys.map(function (k) { return o[k]; }).join('|');

        hash[key] = hash[key] || {};
        hash[key][value] = (hash[key][value] || 0) + 1;
    });

    return array2.every(function (o) {
        var keys = Object.keys(o).sort(),
            key = keys.join('|'),
            value = keys.map(function (k) { return o[k]; }).join('|');

        return hash[key] && hash[key][value] && hash[key][value]--;
    });
}

console.log(compareArrays([{ foo: 'foo', bar: 'bar' }, { baz: 'baz' }], [{ baz: 'baz' }, { foo: 'foo', bar: 'bar' }]));
console.log(compareArrays([{ foo: 'foo', bar: 'bar' }, { baz: 'baz' }, { baz: 'baz' }], [{ baz: 'baz' }, { foo: 'foo', bar: 'bar' }]));
console.log(compareArrays([{ foo: 'foo', bar: 'bar' }, { baz: 'baz' }, { foo: 'baz' }], [{ baz: 'baz' }, { foo: 'foo', bar: 'bar' }]));
console.log(compareArrays([{ foo: 'foo', bar: 'bar' }, { baz: 'baz' }, { foo: 'baz' }], [{ baz: 'baz' }, { foo: 'foo', bar: 'bar' }, { foo: 42 }]));

2 Comments

It doesn't work with objects whose keys or values contain a | though. Or with values that are not strings at all. I'd recommend to use JSON.stringify() on the sorted arrays of keys and values instead.
Also you could simplify by concatenating key and value instead of nesting the lookup table.
0

You can try something like below

  • Reduce multiple objects in each array into one
  • Sort keys and build a 2D array or build a new object
  • Compare the two newly built data structures (2D arrays / objects)

This can be extrapolted to any number of arrays

const arr1 = [{ foo: 'foo', bar: 'bar' }, { baz: 'baz' }]; 
const arr2 = [{ baz: 'baz' }, { foo: 'foo', bar: 'bar' }];

// Method that sorts the object keys and builds a new object
// sortObj = (obj) =>
//   Object.keys(obj).sort().reduce((a, b) => {a[b] = obj[b]; return a}, {})
  
// Method that sorts keys and builds a 2D array
sortObj = (obj) =>
    Object.keys(obj).sort().map((key) => [key, obj[key]])

compareObj = (arr1, arr2) => {
  if(arr1.length !== arr2.length)
     return false;
 
  // 1st array reduce
  const reduceArr1 = arr1.reduce((a, b) => ({...a, ...b}), {});
  
  // 2nd array reduce
  const reduceArr2 = arr2.reduce((a, b) => ({...a, ...b}), {});
  
  // Comparing the sortedObjects
  return JSON.stringify(sortObj(reduceArr1)) === JSON.stringify(sortObj(reduceArr2))
}

console.log(compareObj(arr1, arr2))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.