【问题标题】:How to iterate through deep nested object and find value of a particular key?如何遍历深层嵌套对象并找到特定键的值?
【发布时间】:2020-11-01 00:34:22
【问题描述】:

我有一个如下所示的 Javascript 对象。 我想遍历对象并找出Hostnames的值

const data =
{
  "error1": {
    "7": [
      {
        "ErrorType": "Error-1A",
        "Hostnames": "host123.com,hostabc.com,host33a.com..."
      }
    ],
    "8": [
      {
        "ErrorType": "Error-1B",
        "Hostnames": "host223.com,host2c.com,host43a.com..."
      },
      {
        "ErrorType": "Error-1C",
        "Hostnames": "host1231.com,host2abc.com,host313a.com..."
      }
    ]
  },
  "error2": {
    "3": [
      {
        "ErrorType": "Error-2A"
        "Hostnames": "host1231.com,host2abc.com,host313a.com..."
      },
      {
        "ErrorType": "Error-2B"
        "Hostnames": "host1231.com,host2abc.com,host313a.com..."
      }
    ],
    "8": [
      {
        "ErrorType": "Error-2C"
        "Hostnames": "host1231.com,host2abc.com,host313a.com..."
      },
      {
        "ErrorType": "Error-2D",
        "Hostnames": "host1231.com,host2abc.com,host313a.com..."
      }
    ]
  },
  "error3": {
    "1": [
      {
        "ErrorType": "Error-3A",
        "Hostnames": "host1236.com"
      },
      {
        "ErrorType": "Error-3B",
        "Hostnames": "hostc3231.com"
      }
    ]
  }
}

我编写了以下 NodeJS 函数:

const findObjectByLabel = function(obj, label) {
    if(obj.label === label) { return obj; }
    for(var i in obj) {
        if(obj.hasOwnProperty(i)){
            var foundLabel = findObjectByLabel(obj[i], label);
            if(foundLabel) { return foundLabel; }
        }
    }
    return null;
};

const hostNames = findObjectByLabel(data, 'Hostnames');
console.log(hostNames);

上述函数抛出错误:

Error: undefined : RangeError: Maximum call stack size exceeded

【问题讨论】:

    标签: javascript node.js json foreach collections


    【解决方案1】:

    数据结构需要嵌套循环,但这是可行的。这将提供一个主机名数组:“我想遍历对象并找出主机名的值”。

    const data = {
      "error1": {
        "7": [{
          "ErrorType": "Error-1A",
          "Hostnames": "host123.com,hostabc.com,host33a.com..."
        }],
        "8": [{
            "ErrorType": "Error-1B",
            "Hostnames": "host223.com,host2c.com,host43a.com..."
          },
          {
            "ErrorType": "Error-1C",
            "Hostnames": "host1231.com,host2abc.com,host313a.com..."
          }
        ]
      },
      "error2": {
        "3": [{
            "ErrorType": "Error-2A",
            "Hostnames": "host1231.com,host2abc.com,host313a.com..."
          },
          {
            "ErrorType": "Error-2B",
            "Hostnames": "host1231.com,host2abc.com,host313a.com..."
          }
        ],
        "8": [{
            "ErrorType": "Error-2C",
            "Hostnames": "host1231.com,host2abc.com,host313a.com..."
          },
          {
            "ErrorType": "Error-2D",
            "Hostnames": "host1231.com,host2abc.com,host313a.com..."
          }
        ]
      },
      "error3": {
        "1": [{
            "ErrorType": "Error-3A",
            "Hostnames": "host1236.com"
          },
          {
            "ErrorType": "Error-3B",
            "Hostnames": "hostc3231.com"
          }
        ]
      }
    };
    
    const out = [];
    for (let key in data) {
      for (let number in data[key]) {
        data[key][number].map(d => out.push(d.Hostnames));
      }
    }
    
    console.log(out);

    【讨论】:

      【解决方案2】:

      所以让我们删除无用的上下文。您想深入地在对象中找到“主机名”值。

      而且你的递归似乎是循环的,导致 maximul call stack size exceeded 错误。

      你怎么能自己找到问题?只需添加 `console.log('ON', obj) 作为 'findObjectByLabel' 函数的第一行。

      你会看到你在'E'上循环。因为在某些时候,被测试的对象是一个字符串。

      第二个问题:您检查 .label === 'Hostnames'...在您的 json 数据中没有 'label' 键。

      修复此问题后的另一个问题是您将停在第一个主机名上。

      这里有一个解决方案

      function deepFind(obj, label, results=[]) {
          if( typeof obj !== 'object' && !!obj )
            return null;
      
          if( !!obj[label] ) {
            results.push(obj[label]);
          }
      
          Object.getOwnPropertyNames(obj).forEach( k => {
            deepFind(obj[k], label, results);
          });
      }
      
      const results = [];
      deepFind(data, 'Hostnames', results);
      

      不优雅,但很有效

      【讨论】:

        猜你喜欢
        • 2019-07-18
        • 1970-01-01
        • 2021-07-07
        • 1970-01-01
        • 2011-07-08
        • 1970-01-01
        • 2022-06-13
        • 2020-04-13
        • 1970-01-01
        相关资源
        最近更新 更多