4

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': []
            }
        }
    }
}
7
  • Please post your data. Commented Jun 9, 2013 at 9:33
  • 1
    You could use normal for or for...in loops instead ;) Commented Jun 9, 2013 at 9:34
  • i made danml.com/js/oquery.js to use css attrib-style queries for this sort of thing, you call like oQuery(worldHandler.world, "[id=123]") to find the units with the id of 123... Commented Jun 9, 2013 at 9:46
  • @dandavis Thanks, looks very interesting! Is it performant too? Commented Jun 9, 2013 at 10:00
  • @thg435 Just posted some example data! Commented Jun 9, 2013 at 10:00

2 Answers 2

6

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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];

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.