5

I have 2 arrays of objects and I have to compare them, but the order of the objects DOES NOT matter. I can't sort them because I won't have their keys' names because the functions must be generic. The only information that I'll have about the array is that both array's objects have the same amount of keys and those keys have the same name. So the array1 must contain the same objects as the array2.

var array1 = [{"key1":"Banana", "key2":"Yammy"}, {"key1":"Broccoli", "key2":"Ew"}];
var array2 = [{"key1":"Broccoli", "key2":"Ew"}, {"key1":"Banana", "key2":"Yammy"}];

In the example, array1 must be equal array2. I tryed to use the chai .eql() method but it didn't work.

mplungjan
  • 169,008
  • 28
  • 173
  • 236
Brian Batista
  • 67
  • 1
  • 6

3 Answers3

7

The following solution:

  • will verify that the arrays have an equal number of elements
  • does not impose restrictions on keys (as to not contain a certain delimiter)
  • requires both keys and (string) values to be the same
  • has a time complexity of O(nlogn) (instead of O(n²) as some other solutions here)

function equalArrays(a, b) {
    if (a.length !== b.length) return false;
    const ser = o => JSON.stringify(Object.keys(o).sort().map( k => [k, o[k]] ));
    a = new Set(a.map(ser));
    return b.every( o => a.has(ser(o)) );
}

// Example
var array1 = [{"key1":"Banana", "key2":"Yammy"}, {"key1":"Broccoli", "key2":"Ew"}];
var array2 = [{"key1":"Broccoli", "key2":"Ew"}, {"key1":"Banana", "key2":"Yammy"}];
console.log(equalArrays(array1, array2)); // true
// Example with different key name
var array1 = [{"key0":"Banana", "key2":"Yammy"}, {"key1":"Broccoli", "key2":"Ew"}];
var array2 = [{"key1":"Broccoli", "key2":"Ew"}, {"key1":"Banana", "key2":"Yammy"}];
console.log(equalArrays(array1, array2)); // false
trincot
  • 317,000
  • 35
  • 244
  • 286
1

You can array#join each value of the object on an separator and then generate a new array of string and then compare each values using array#every and array#includes

var array1 = [{"key1":"Banana", "key2":"Yammy"}, {"key1":"Broccoli", "key2":"Ew"}];
    array2 = [{"key1":"Broccoli", "key2":"Ew"}, {"key1":"Banana", "key2":"Yammy"}];
    values = (o) => Object.keys(o).sort().map(k => o[k]).join('|'),
    mapped1 = array1.map(o => values(o)),
    mapped2 = array2.map(o => values(o));

var res = mapped1.every(v => mapped2.includes(v));

console.log(res);
Hassan Imam
  • 21,956
  • 5
  • 41
  • 51
  • 1
    This may fail when one array has more entries than the other, when a key has the pipe symbol, when objects have different keys, ... – trincot Oct 31 '17 at 18:40
  • It worked like a charm. There is an easy way to print an array of objects that doesn't match? For exemple, if instead of "Banana" one of the arrays have "Bananas". – Brian Batista Oct 31 '17 at 18:41
  • @trincot, I'm verifying the length of the arrays before comparing the objects. – Brian Batista Oct 31 '17 at 18:43
  • Examples of wrong results: change first `"key1"` to `"key0"`: result is still true. Or, remove `"key2": "Yammy"` and change `"Banana"` to `"Banana|Yammy"`: result is still true. – trincot Oct 31 '17 at 18:46
  • @trincot You are correct on both account, but the question mentioned that `The only information that I'll have about the array is that both array's objects have the same amount of keys and those keys have the same name.` – Hassan Imam Oct 31 '17 at 19:18
  • Still then you can have values `Banana|Yammy` and `Nice` compared with `Banana` and `Yammy|Nice` and have equality. Also running time is *O(n²)*. – trincot Oct 31 '17 at 20:55
0

You can do something like following:

For each object in each array you can calc its representation:

arr1.forEach( (obj) => {
    obj.representation = '';
    for (let key of Object.keys(obj)) {
      obj.representation += obj[key];
    }
}

Same for arr2

now you can sort both arrays by representation for example and then compare.

To sort do the following:

arr1.sort( (a,b) => { return a.representation > b.representation } );
arr2.sort( (a,b) => { return a.representation > b.representation } );

After sorting you can compare both arrays

let equal = arr1.every( (el, i) => arr2[i]===el );
komron
  • 2,267
  • 2
  • 17
  • 26