我需要一个javascript递归函数,当key和json对象传递给这个函数时返回一个值数组

时间:2015-11-25 09:46:53

标签: javascript arrays recursion

我需要一个javascript递归函数,当key和JavaScript对象传递给这个函数时返回一个值数组。

请注意,嵌套的JavaScript对象具有未知深度。该函数工作正常,但它返回重复。

   function getValuesByKey(object, key) {
    var values = [];
    recursiveFx(object);
    function recursiveFx(object) {
      for (var property in object) {
        if (object.hasOwnProperty(property)) {
          if (typeof object[property] == "object") {
           recursiveFx(object[property]);
          } else {
            //found a property which is not an object
            try {
              if (isDefined(object[key])) {
                console.log('Here is the value that is to be pushed',object[key]);
                values.push(object[key]);
              }
            } catch (e) {

            }
          }
        }
      }
    }
    return values;
  } 

这是isDefined辅助函数

function isDefined(variable) {
    try {
    if (typeof(variable) !== 'undefined') return true;
    } catch (e) {
      return false;
    }
  }

以下是JavaScript对象的示例:

{
      "children": [{
        "id": "5",
        "parentid": "0",
        "text": "Device Guides",
        "index": "1",
        "children": [{
          "id": "10",
          "index": "0",
          "text": "Grandstream GXP-21XX"
        }, {
          "id": "11",
          "index": "1",
          "text": "Polycom Soundstation/Soundpoint"
        }, {
          "id": "23",
          "parentid": "8",
          "index": "2",
          "text": "New Polycom",
          "children": [{
            "id": "5",
            "parentid": "0",
            "text": "Device Guides",
            "index": "1",
            "children": [{
              "id": "10",
              "index": "0",
              "text": "Grandstream GXP-21XX"
            }, {
              "id": "11",
              "index": "1",
              "text": "Polycom Soundstation/Soundpoint"
            }, {
              "id": "23",
              "index": "2",
              "text": "New Polycom"
            }]
          }, {
            "id": "6",
            "parentid": "0",
            "text": "Pre-Sales Evaluation",
            "index": "0",
            "children": []
          }, {
            "id": "7",
            "parentid": "0",
            "text": "Router Setup Guides",
            "index": "2",
            "children": [{
              "id": "9",
              "index": "0",
              "text": "Sonicwall"
            }, {
              "id": "12",
              "index": "1",
              "text": "Cisco"
            }]
          }]
        }, {
          "id": "6",
          "parentid": "0",
          "text": "Pre-Sales Evaluation",
          "index": "0",
          "children": []
        }, {
          "id": "7",
          "parentid": "0",
          "text": "Router Setup Guides",
          "index": "2",
          "children": [{
            "id": "9",
            "index": "0",
            "text": "Sonicwall"
          }, {
            "id": "12",
            "index": "1",
            "text": "Cisco"
          }]
        }]}]};

当我运行此getValuesByKey(jsonObj, 'id');时,我得到以下数组:

["5", "5", "5", "5", "10", "10", "10", "11", "11", "11", "23", "23", "23", "23", "5", "5", "5", "5", "10", "10", "10", "11", "11", "11", "23", "23", "23", "6", "6", "6", "6", "7", "7", "7", "7", "9", "9", "9", "12", "12", "12", "6", "6", "6", "6", "7", "7", "7", "7", "9", "9", "9", "12", "12", "12"]

请注意,5已被返回4次而不是2次

3 个答案:

答案 0 :(得分:7)

您每次通过循环检查对象属性是否存在key 。因此,您获得的值与对象上的属性一样多。所以:

function getValuesByKey(object, key) {
  var values = [];
  recursiveFx(object);
  function recursiveFx(object) {

    if (key in object) values.push(object[key]);
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    for (var property in object) {
      if (object.hasOwnProperty(property)) {
        if (typeof object[property] == "object") {
         recursiveFx(object[property]);
        }
      }
    }
  }
  return values;
} 

替代方案:将JSON.stringify与替换者

一起使用

无论如何,您可以使用

更轻松地完成此操作
function getValuesByKey(object, key) {
  var values = [];
  JSON.stringify(object, function(k, v) { 
    if (k === key) values.push(v);
    return v;
  });
  return values;
}

这使用replacer参数JSON.stringify拦截每个键值对。字符串化的值本身我们不需要扔掉。

答案 1 :(得分:2)

只是一个递归的想法:

var data = { "children": [{ "id": "5", "parentid": "0", "text": "Device Guides", "index": "1", "children": [{ "id": "10", "index": "0", "text": "Grandstream GXP-21XX" }, { "id": "11", "index": "1", "text": "Polycom Soundstation/Soundpoint" }, { "id": "23", "parentid": "8", "index": "2", "text": "New Polycom", "children": [{ "id": "5", "parentid": "0", "text": "Device Guides", "index": "1", "children": [{ "id": "10", "index": "0", "text": "Grandstream GXP-21XX" }, { "id": "11", "index": "1", "text": "Polycom Soundstation/Soundpoint" }, { "id": "23", "index": "2", "text": "New Polycom" }] }, { "id": "6", "parentid": "0", "text": "Pre-Sales Evaluation", "index": "0", "children": [] }, { "id": "7", "parentid": "0", "text": "Router Setup Guides", "index": "2", "children": [{ "id": "9", "index": "0", "text": "Sonicwall" }, { "id": "12", "index": "1", "text": "Cisco" }] }] }, { "id": "6", "parentid": "0", "text": "Pre-Sales Evaluation", "index": "0", "children": [] }, { "id": "7", "parentid": "0", "text": "Router Setup Guides", "index": "2", "children": [{ "id": "9", "index": "0", "text": "Sonicwall" }, { "id": "12", "index": "1", "text": "Cisco" }] }] }] };

function getValuesByKey(object, key) {
    var values = [];

    function r(obj) {
        Object.keys(obj).forEach(function (k) {
            if (Array.isArray(obj[k])) {
                obj[k].forEach(r);
                return;
            }
            if (typeof obj[k] === 'object') {
                r(obj[k]);
                return;
            }
            k === key && !~values.indexOf(obj[k]) && values.push(obj[k]);
        });
    }

    r(object);
    return values;
}

document.write('<pre>' + JSON.stringify(getValuesByKey(data, 'id'), 0, 4) + '</pre>');

答案 2 :(得分:0)

好的我明白了,你的代码中有一个错误。测试if(isDefined(object [key])){

时应测试该键=== property

否则,只要在另一个属性中检查具有该值的对象时,您只需添加匹配值(如果明确的话):)