【问题标题】:iterating through object遍历对象
【发布时间】:2013-10-19 20:41:13
【问题描述】:

我很难找到一种方法来以我想要的方式遍历这个对象。我在这里只使用 Javascript。

首先,这是对象

{
"dialog":
{
    "dialog_trunk_1":{
        "message": "This is just a JSON Test"
    },
    
    "dialog_trunk_2":{
        "message": "and a test of the second message"
    },

    "dialog_trunk_3":
    {
        "message": "This is a test of a bit longer text. Hopefully this will at the very least create 3 lines and trigger us to go on to another box. So we can test multi-box functionality, too."
    }
}
}

现在,我只是在尝试基本的方法来访问该对象上的每个 dialog_trunk。理想情况下,我想遍历对象并为每个主干显示它的 message 值。

我尝试使用 for 循环动态生成 dialog_trunk 的名称/编号,但我无法使用对象名称的字符串访问该对象,所以我不确定从这里去哪里.

【问题讨论】:

  • 你需要一个 for..in 循环
  • 如果可能,您应该更改结构以使用有序列表。使用具有递增索引的命名键几乎没有意义。 {"dialog":{"trunks":[{"message":"..."},{"message":"..."}]}}
  • 如果是JSON,你解析了吗?
  • @dcp 你很有用,谢谢。也许下次我会尝试包括我找不到与我自己的结构足够相似的东西,我可以找出正确的方法。这些天不得不明确说明,这是一种耻辱。

标签: javascript object


【解决方案1】:

var res = {
              "dialog":
              {
                  "dialog_trunk_1":{
                      "message": "This is just a JSON Test"
                  },

                  "dialog_trunk_2":{
                      "message": "and a test of the second message"
                  },

                  "dialog_trunk_3":
                  {
                      "message": "This is a test of a bit longer text. Hopefully this will at the very least create 3 lines and trigger us to go on to another box. So we can test multi-box functionality, too."
                  }
              }
          }


for (var key in res) {
  if (res.hasOwnProperty(key)) {
    var val = res[key];
    for (var key in val) {
      if (val.hasOwnProperty(key)) {
        var dialog = val[key];
        console.log(dialog.message);
      }
    }
  }
}

【讨论】:

    【解决方案2】:

    @schirrmacher 建议的递归方法的改进版本,用于打印整个对象的 key[value]:

    var jDepthLvl = 0;
    function visit(object, objectAccessor=null) {
      jDepthLvl++;
      if (isIterable(object)) {
        if(objectAccessor === null) {
          console.log("%c ⇓ ⇓ printing object $OBJECT_OR_ARRAY$ -- START ⇓ ⇓", "background:yellow");
        } else
          console.log("%c"+spacesDepth(jDepthLvl)+objectAccessor+"%c:","color:purple;font-weight:bold", "color:black");
        forEachIn(object, function (accessor, child) {
          visit(child, accessor);
        });
      } else {
        var value = object;
        console.log("%c"
          + spacesDepth(jDepthLvl)
          + objectAccessor + "[%c" + value + "%c] "
          ,"color:blue","color:red","color:blue");
      }
      if(objectAccessor === null) {
        console.log("%c ⇑ ⇑ printing object $OBJECT_OR_ARRAY$ -- END ⇑ ⇑", "background:yellow");
      }
      jDepthLvl--;
    }
    
    function spacesDepth(jDepthLvl) {
      let jSpc="";
      for (let jIter=0; jIter<jDepthLvl-1; jIter++) {
        jSpc+="\u0020\u0020"
      }
      return jSpc;
    }
    
    function forEachIn(iterable, functionRef) {
      for (var accessor in iterable) {
        functionRef(accessor, iterable[accessor]);
      }
    }
    
    function isIterable(element) {
      return isArray(element) || isObject(element);
    }
    
    function isArray(element) {
      return element.constructor == Array;
    }
    
    function isObject(element) {
      return element.constructor == Object;
    }
    
    
    visit($OBJECT_OR_ARRAY$);
    

    【讨论】:

      【解决方案3】:

      为此,您使用for..in 循环。请务必检查对象是否拥有属性或所有继承的属性是否也显示。一个例子是这样的:

      var obj = {a: 1, b: 2};
      for (var key in obj) {
        if (obj.hasOwnProperty(key)) {
          var val = obj[key];
          console.log(val);
        }
      }
      

      或者如果您需要递归遍历所有属性:

      var obj = {a: 1, b: 2, c: {a: 1, b: 2}};
      function walk(obj) {
        for (var key in obj) {
          if (obj.hasOwnProperty(key)) {
            var val = obj[key];
            console.log(val);
            walk(val);
          }
        }
      }
      walk(obj);
      

      【讨论】:

      【解决方案4】:

      这是我的递归方法:

      function visit(object) {
          if (isIterable(object)) {
              forEachIn(object, function (accessor, child) {
                  visit(child);
              });
          }
          else {
              var value = object;
              console.log(value);
          }
      }
      
      function forEachIn(iterable, functionRef) {
          for (var accessor in iterable) {
              functionRef(accessor, iterable[accessor]);
          }
      }
      
      function isIterable(element) {
          return isArray(element) || isObject(element);
      }
      
      function isArray(element) {
          return element.constructor == Array;
      }
      
      function isObject(element) {
          return element.constructor == Object;
      }
      

      【讨论】:

      • 做得很好!效果很好!如何将键作为字符串添加到值前面,例如:key:value?
      【解决方案5】:

      我的问题实际上是 JSON 对象规划不当的问题,而不是实际的逻辑问题。根据 user2736012 的建议,我最终将对象组织如下。

      {
      "dialog":
      {
          "trunks":[
          {
              "trunk_id" : "1",
              "message": "This is just a JSON Test"
          },
          {
              "trunk_id" : "2",
              "message": "This is a test of a bit longer text. Hopefully this will at the very least create 3 lines and trigger us to go on to another box. So we can test multi-box functionality, too."
          }
          ]
      }
      }
      

      那时,我可以根据对象的总数做一个相当简单的 for 循环。

      var totalMessages = Object.keys(messages.dialog.trunks).length;
      
          for ( var i = 0; i < totalMessages; i++)
          {
              console.log("ID: " + messages.dialog.trunks[i].trunk_id + " Message " + messages.dialog.trunks[i].message);
          }
      

      不过,并非所有浏览器都支持我获取 totalMessages 的方法。对于我的项目,这实际上并不重要,但是如果您选择使用类似的东西,请注意这一点。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-07-15
        • 2015-01-11
        • 2017-12-17
        • 1970-01-01
        相关资源
        最近更新 更多