javascriptlodashobject-comparison

Comparing an two objects with arrays for quality


I am currently building a filter system and I am encountering a problem where I want to prevent double filtering if the order of array elements are changed.

For example, I got this object:

const filters = {
  brands: [],
  models: [],
}

User A chooses the brand Audi (id 5f1d5077b261aa63f42cc8a9) and BMW (id 5f1d5077b261aa63f42cc8aa) So you get this object:

{
  brands: ["5f1d5077b261aa63f42cc8a9", "5f1d5077b261aa63f42cc8aa"],
  models: [],
}

User B does the same, but in opposite (so first BMW, then Audi). So we end up with this:

{
  brands: ["5f1d5077b261aa63f42cc8aa", "5f1d5077b261aa63f42cc8a9"],
  models: [],
}

(Notice the difference between the order of brands)

Now when I check these for equality using Lodash isEqual with this code:

const _ = require("lodash");

const filtersA = {
    brands: ["5f1d5077b261aa63f42cc8a9", "5f1d5077b261aa63f42cc8aa"],
    models: [],
};

const filtersB = {
    brands: ["5f1d5077b261aa63f42cc8aa", "5f1d5077b261aa63f42cc8a9"],
    models: [],
};

console.log(_.isEqual(filtersA, filtersB));

This returns false unfortunately, then I tried comparing only the brands together, like:

console.log(_.isEqual(filtersA.brands, filtersB.brands);

That also returns false.

My goal is to return true if the filters in the object are equal, without looking at the order of the other filter. As long as the same items exist it should return true

I also read something about Lodash isEqualWith, but I am not really understanding how to use it.


Solution

  • I fixed it using the following function, this will only work if the two objects have the same structure.

    const _ = require("lodash");
    
    const filtersA = {
        brands: ["5f1d5077b261aa63f42cc8a9", "5f1d5077b261aa63f42cc8aa"],
        models: [],
    };
    
    const filtersB = {
        brands: ["5f1d5077b261aa63f42cc8aa", "5f1d5077b261aa63f42cc8a9"],
        models: [],
    };
    
    /**
     * Checks if two objects with arrays are equal
     *
     * @param {Object} a
     * @param {Object} b
     */
    const areObjectWithArraysEqual = (a, b) => Object.keys(a).every((key) => _.isEqual(a[key].sort(), b[key].sort()));
    
    console.log(areObjectWithArraysEqual(filtersA, filtersB));
    

    This returns true as expected