【问题标题】:How do you search object for a property within property?您如何在属性中搜索对象以查找属性?
【发布时间】:2015-04-13 12:34:43
【问题描述】:

我有这个对象:

key = {
    spawn:{type:1,img:app.assets.get('assets/spawn.svg')},
    wall:{type:2,img:app.assets.get('assets/wall.svg')},   
    grass:{type:3,img:app.assets.get('assets/grass.svg')},
    spike:{type:4,img:app.assets.get('assets/spike.svg')},
    ground:{type:5,img:app.assets.get('assets/ground.svg')}
  };

我有一个只有类型的数组,我需要将给定的图像添加到它,数组看起来像这样:

[{type:1,image:null},{type:3,image:null},{type:2,image:null},{type:2,image:null},{type:5,image:null}]

基本上我想循环数组,在key对象中找到类型并获取给定的图像并将其保存到数组中。

有什么简单的方法吗?

【问题讨论】:

  • 到目前为止你尝试过什么代码?我们倾向于只帮助现有代码,而不是为您编写所有代码。
  • 我现在不想把它放在一起,但对于热情的人来说,这是一个简单的单线。
  • 这实际上是一个很好的问题,值得点赞,特别是如果它得到了一个很好的答案(现有的答案不是现代的 Javascript)。我很快就会赏金。
  • @Andy 问题是,通常很难从猜测尝试中找到好的答案。代码尝试通常有助于澄清一个人实际上在尝试做什么,但我认为考虑到可编译的输入和输出,代码已经足够清晰了。
  • @Andy meta.stackexchange.com/a/179038/183887 了解需要研究工作的背景。我确实认为 OP 的表述构成了研究工作,并且无论如何它都满足了研究工作的目的。您的评论“SO 不是编码服务”似乎不相关。

标签: javascript arrays object search


【解决方案1】:

对我来说最突出的一点是这条线

...获取给定的图像并将其保存到数组中

我假设这意味着原始数组。我认为更好的方法是将适当的键和值映射到一个新数组,但对于这个例子,我假设这是一个要求。

为了尽量保持解决方案的简洁性和对 lodash 解决方案的要求:

_.each(key, function(prop){
    _.each(_.filter(types, { type: prop.type }), function(type) { type.image = prop.img });
});

【讨论】:

  • 享受达到 1000 次代表 :)
【解决方案2】:

给定键的对象和这样的对象数组:

var key = {
    spawn:{type:1,img:app.assets.get('assets/spawn.svg')},
    wall:{type:2,img:app.assets.get('assets/wall.svg')},   
    grass:{type:3,img:app.assets.get('assets/grass.svg')},
    spike:{type:4,img:app.assets.get('assets/spike.svg')},
    ground:{type:5,img:app.assets.get('assets/ground.svg')}
};
var arr = [{type:1,image:null},{type:3,image:null},{type:2,image:null},{type:2,image:null},{type:5,image:null}];

我们可以首先在对象key 中创建一个属性数组,以使其迭代更简单。 然后遍历数组arr,并在每个成员上,使用some 循环检查哪个图像属于该成员的类型(一些返回第一个true 并结束循环)。

如果您希望循环没有副作用并且不改变原始数组,您可以将forEach 更改为map(并将返回的新数组分配给arr 或新变量) .

var keyTypes = Object.keys(key);
arr.forEach(function (item) {
    keyTypes.some(function (keyType) {
        if (key[keyType].type === item.type) {
            item.image = key[keyType].img;
            return true;
        }
        return false;
    });
});

更聪明的做法是更改图像类型的对象,以便您可以将类型用作访问属性,或者为此创建另一个对象(如另一个答案中所指出的那样)。

【讨论】:

    【解决方案3】:

    我不确定这个解决方案是否现代,但它不使用任何循环或递归。

    object = {
        spawn: {type:1, img:app.assets.get('assets/spawn.svg')},
        wall: {type:2, img:app.assets.get('assets/wall.svg')},   
        grass: {type:3, img:app.assets.get('assets/grass.svg')},
        spike: {type:4, img:app.assets.get('assets/spike.svg')},
        ground: {type:5, img:app.assets.get('assets/ground.svg')}
    };
    arr = [
        {type:1, image:null},
        {type:3, image:null},
        {type:2, image:null},
        {type:2, image:null},
        {type:5, image:null}
    ];
    
    var typeImages = {};
    Object.getOwnPropertyNames(object).forEach(function(value){
        typeImages[object[value].type] = object[value].img;
    });
    arr = arr.map(function(value){
        return {
            type: value.type,
            image: typeImages[value.type]
        };
    });
    

    【讨论】:

      【解决方案4】:
      var key = {
          spawn:{type:1,img:app.assets.get('assets/spawn.svg')},
          wall:{type:2,img:app.assets.get('assets/wall.svg')},   
          grass:{type:3,img:app.assets.get('assets/grass.svg')},
          spike:{type:4,img:app.assets.get('assets/spike.svg')},
          ground:{type:5,img:app.assets.get('assets/ground.svg')}
        };
      var typesArray = [{type:1,image:null},{type:3,image:null},{type:2,image:null},{type:2,image:null},{type:5,image:null}];
      
      for(var i = 0, j = typesArray.length; i < j; i++)
      {
          typesArray[i].image = getKeyObjectFromType(typesArray[i].type).img;
      }
      
      function getKeyObjectFromType(type)
      {
          for(var k in key)
          {
              if(key[k].type == type)
              {
                  return key[k];
              }
          }
          return {};
      }
      

      【讨论】:

        【解决方案5】:
        for (var i = 0; i < typesArray.length; i++) {
            for (prop in key) {
                if (key[prop].type === typesArray[i].type) {
                    typesArray[i].image = key[prop].img;
                }
            }
        }
        

        它遍历数组(“typesArray”),并且对于每个数组项,它会遍历 key 中的所有对象,以寻找具有相同“类型”的对象。当它找到它时,它会获取该关键对象的“img”并保存到数组中。

        【讨论】:

        • 请添加一些关于如何解决问题的解释
        【解决方案6】:

        使用 lodash (https://lodash.com/):

        var key = {
            spawn:{type:1,img:app.assets.get('assets/spawn.svg')},
            wall:{type:2,img:app.assets.get('assets/wall.svg')},   
            grass:{type:3,img:app.assets.get('assets/grass.svg')},
            spike:{type:4,img:app.assets.get('assets/spike.svg')},
            ground:{type:5,img:app.assets.get('assets/ground.svg')}
        };
        
        var initialList = [{type:1,image:null},{type:3,image:null},{type:2,image:null},{type:2,image:null},{type:5,image:null}];
        
        var updatedList = _.transform(initialList, function(result, item) {
            item.image = _.find(key, _.matchesProperty('type', item.type)).img;
            result.push(item);
        });
        

        这将遍历initialList 中的每个项目,在key 中找到与其type 属性匹配的对象并将其放入image 属性中。

        最终结果将在updatedList

        【讨论】:

        • 您可以快速生成初始列表。一般来说,最好避免就地更新对象,或者让框架处理它,即更坚定地做事(这只是我突然想到的——我现在也在学习最佳实践)。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-12-24
        • 2021-05-26
        • 1970-01-01
        • 2015-11-05
        • 2011-08-20
        • 2013-03-09
        相关资源
        最近更新 更多