Reputation: 12037
In my game, I need find a certain monster that is contained in an "units" array. This array is inside a spatial cell structure inside a world object. How can I find this unit without writing ugly code?
var foundUnit = null;
_.each(worldHandler.world, function(zone) {
if ( foundUnit ) return;
_.each(zone, function(cellX) {
if ( foundUnit ) return;
_.each(cellX, function(cellY) {
if ( foundUnit ) return;
if ( !_.isUndefined(cellY.units) ) {
_.each(cellY.units, function(unit) {
if ( foundUnit ) return;
if ( unit.id === id ) foundUnit = unit;
});
}
});
});
});
return foundUnit;
The trouble here is that I can't use return when I found the right value. Return inside the _.each() will just continue that current loop. Is there a better/cleaner way to find a certain value inside a nested object?
Example data:
{ // World
'1': { // Zone
'-1': { // Cell X
'-1': { // Cell Y
'units': []
},
'0': {
'units': [{id:5}]
},
'1': {
'units': []
}
}
} {
'0': {
'-1': {
'units': []
},
'0': {
'units': []
},
'1': {
'units': []
}
}
} {
'1': {
'-1': {
'units': []
},
'0': {
'units': []
},
'1': {
'units': []
}
}
}
}
Upvotes: 4
Views: 6592
Reputation: 8981
You could flatten your nested structure into an array of units and then use _.find
on it:
var zones = _.flatten(_.map(world, _.values));
var cells = _.flatten(_.map(zones, _.values));
var units = _.flatten(_.map(cells, _.values));
var unit = _.find(units, function(u) { return u.id == 7 });
If you're concerned about performance and you're looking up by unit.id
then you should consider building an index:
var indexById = {};
_.each(units, function(u) {
indexById[u.id] = u;
});
Then you can do constant time lookups: var unit = indexById[7];
Upvotes: 1
Reputation:
Check out _.some
.
var foundUnit = null;
_.some(worldHandler.world, function(zone) {
return _.some(zone, function(cellX) {
return _.some(cellX, function(cellY) {
return _.some(cellY.units, function(unit) {
if ( unit.id === id ) {foundUnit = unit; return true; }
});
});
});
});
return foundUnit;
Note that _.some
no-ops if the object is null, so no need to check for that.
Upvotes: 6