如何使用下划线的每个函数有效地在嵌套对象中查找值?

时间:2013-06-09 09:25:03

标签: javascript underscore.js

在我的游戏中,我需要找到一个包含在“单位”数组中的怪物。此数组位于世界对象内的空间单元结构内。如何在不编写丑陋代码的情况下找到此单元?

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;

这里的麻烦是当我找到正确的值时我不能使用return。返回_.each()内部只会继续当前循环。是否有更好/更清晰的方法在嵌套对象中找到某个值?

示例数据:

{ // 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': []
            }
        }
    }
}

2 个答案:

答案 0 :(得分:6)

结帐_.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;

如果对象为null,请注意_.some no-ops,因此无需检查。

答案 1 :(得分:1)

您可以将嵌套结构展平为一个单元数组,然后在其上使用_.find

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 });

如果您对性能感到担心,并且您在unit.id查找,那么您应该考虑建立一个索引:

var indexById = {};
_.each(units, function(u) {
    indexById[u.id] = u;
});

然后你可以进行恒定时间查找:var unit = indexById[7];