Compare collections in javascript

In testing an API, I wanted to verify not just the response, but also ensure that the desired changes happened in the database. To test, I can compare an expected value of a collection verse a queried value (e.g. Did my code really delete the item).

Use-case

Below are two collections I want to compare. The only thing you need to know is that they are “equal”, but they the two top-most objects are flipped within their arrays. This situation arose from querying my no-sql DB. The order is often unpredictable. I didn’t want to always force an order.

Collection 1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
[
{
id: '1234',
a: {
b: 'c',
d: 'e'
},
f: [
{
g: 'h'
},
{
i: 'j'
}
]
},
{
id: '1235',
a: {
b: 'c',
d: 'e'
},
f: [
{
g: 'h'
},
{
i: 'j'
}
]
}
]

Collection 2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
[
{
id: '1235',
a: {
b: 'c',
d: 'e'
},
f: [
{
g: 'h'
},
{
i: 'j'
}
]
},
{
id: '1234',
a: {
b: 'c',
d: 'e'
},
f: [
{
g: 'h'
},
{
i: 'j'
}
]
}
]

Possible Solutions

Stringify?

Using JSON.stringify() has potential for comparing most objects. (See this stack overflow post for more info about why you can’t just compare two objects). You would stringify each object then compare the strings. However, since these items are out of order that, will not work.

Library solution

I’m hoping I’m wrong, but I just couldn’t find a library solution (ideally lodash). Unfortuantely, pushing the arrays into _.isEqual() didn’t work.

A solution for my needs

First step, let’s get these in order. I use lodash’s _.sortBy() method.

If I get these sorted, then _.isEqual() will work. Again, no luck. But that’s ok, I can resort to the old stringify trick now that I’m confident in my order.

Here’s my final method:

1
2
3
4
5
6
7
8
collectionsAreEqual: function(collection1, collection2, sortBy) {
// Sort conditions so the arrays match up.
sortBy = sortBy || 'id';
collection1 = _.sortBy(collection1, sortBy);
collection2 = _.sortBy(collection2, sortBy);
return JSON.stringify(collection1) === JSON.stringify(collection2);
}

Tip: If you break up that return statement, you can choose to log to the console the differing collections upon failure. I find that helpful.

avatar

Dev Blog