Keeano Keeano - 5 months ago 84
AngularJS Question

Trying to return a deep nested object with Lodash

I have not been able to find a solution for this on StackoverlFlow and i have been working on this issue for some time now. Its a bit difficult so please let me know if i should provide more information.

My problem:
I have a JSON object of Lands, each land has an ID and a Blocks array associated with it and that blocks array has block with ID's too.

Preview:

var Lands = [{
'LandId':'123',
'something1':'qwerty',
'something2':'qwerty',
'Blocks': [
{
'id':'456',
'LandId':'123'
},
{
'BlockId':'789',
'LandId':'123'
}
]
},
...More Land Objects];


Note: The data is not setup the way i would have done it but this was done along time ago and i have to work with what i have for right now.

I am trying to write a lodash function that will take the blockId's that i have and match them and return the landId from the Blocks.

so the end result would be a list of LandId's that where returned from the Blocks.

I was using something like this and it was returning no results:

selectedLand = function(Lands, landIDs){
return _.filter(Lands, function(land){
return land === landIDs[index];
});
};


I know i am going about this the wrong way and would like to know the appropriate way to approach this and solve it. any help is much appreciated.

Answer
selectedLand = function(Lands, landIDs){
                return _.filter(Lands, function(land){
                    return land === landIDs[index];
                });
            };

Note that index lacks any definition in this scope, so this function will essentially never return true, barring a lucky(?) accident with an externally defined index. And anytime you call _.filter(someArr,function(){return false;}) you'll get []. Undefined index aside, this does strict comparison of a land object against (maybe) a string in landIDs

I'm a bit unclear on the exact requirements of your selection, so you can tailor this filter to suit your needs. The function filters the lands array by checking if the .blocks array property has some values where the .landID property is included in the landsID array.

In closing, if you want to make the most out of lodash (or my favorite, ramda.js) I suggest you sit down and read the docs. Sounds deathly boring, but 75% of the battle with data transforms is knowing what's in your toolbox. Note how the English description of the process matches almost exactly with the example code (filter, some, includes).

var Lands = [{
    'LandId': '123',
    'something1': 'qwerty',
    'something2': 'qwerty',
    'Blocks': [{
      'id': '456',
      'LandId': '123'
    }, {
      'BlockId': '789',
      'LandId': '123'
    }]
  }
];

// assuming lands is like the above example
// and landIDs is an array of strings
var selectLandsWithBlocks = function(lands, landIDs) {
  return _.filter(lands, function(land) {    
    var blocks = land.Blocks;
    var blockHasALandId = function(block) {
      return _.includes(landIDs,block.LandId);
    };
    return _.some(blocks, blockHasALandId);
  });
};

console.log(selectLandsWithBlocks(Lands,[]));
console.log(selectLandsWithBlocks(Lands,['mittens']));
console.log(selectLandsWithBlocks(Lands,['123']));
<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/4.13.1/lodash.min.js"></script>