John Lippson
John Lippson

Reputation: 1319

Using underscore to determine if an object exists in a deeply nested array of objects?

This comparison is a bit odd as I have the following format:

Preferences Object:

{ 
  models: [
   {... attributes: {} },
   {... attributes: {} },
   {... attributes: {} }
  ]
}

Data Array:

[{}, {}, {}]

I have this object that contains an array of more objects with a key called attributes.

My Goal:

My goal is to see which items in the Data Array don't exist as the value to the attributes key in the models array using Underscore.JS.

Hacky Attempt:

This is definitely not how I want to code this, but localStorageLayers is the Data Array and the layerPrefs is the Preferences Object is the above labelling.

_.each(localStorageLayers, (localLayer) => {
    var layerWasLoaded = false;
    _.each(layerPrefs.models, (layerPref) => {
        if (_.isEqual(layerPref.attributes, localLayer)) {
            layerWasLoaded = true;
            // Don't do anything
        }
    })
    if (layerWasLoaded == false) {
        // Do stuff
    }
})

Upvotes: 0

Views: 319

Answers (1)

user9366559
user9366559

Reputation:

You could filter the localStorageLayers down to a subset where the localLayer is found to be equal to none (negated some) of the layerPrefs.models objects as compared to its attributes property.

I don't use lodash, but result should contain only the localStorageLayers that did not find equality in layerPrefs.models.

const layerPrefs = { 
  models: [
   {attributes: {foo: "foo"} },
   {attributes: {foo: "bar"} },
   {attributes: {baz: "baz"} }
  ]
};

const localStorageLayers = [
  {foo: "foo"}, {hot: "dog"}, {hot: "dog"}, {baz: "baz"}
];

const result = _.filter(localStorageLayers, localLayer => 
    !_.some(layerPrefs.models, layerPref =>
        _.isEqual(layerPref.attributes, localLayer)
    )
);

console.log(result);

// Remove duplicates
const noDupes = _.uniqBy(result, _.isEqual);

console.log(noDupes);
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>


You could reverse the evaluation of each localLayer by doing _.every with !_.isEqual.

Use which ever seems clearer.

const result = _.filter(localStorageLayers, localLayer => 
    _.every(layerPrefs.models, layerPref =>
        !_.isEqual(layerPref.attributes, localLayer)
    )
);

Upvotes: 1

Related Questions