如何为以后的迭代创建递归对象树数组



我的问题与此略有相似。

所以,假设我有一个这样的对象:

var obj = {
  'a': {
    'b': {
      'c': 1,
      'd': 2
    },
    'e': 3
  },
  'f': 4,
  'g': 5
};

我想通过一个函数运行它并创建一个看起来像这样的数组:

var arr =
  'a',
  'a.b',
  'a.b.c',
  'a.b.d',
  'a.e',
  'f',
  'g'
];

该数组的目的是让我以后可以以完全相同的方式遍历具有相同分层格式的对象。我不确定如何执行此步骤。

因此,给定objarr,它将使用for循环来访问obj中的所有键值对。据我所知,您无法访问这样的嵌套属性:obj['a.b.c'],所以我不确定如何做到这一点。

澄清编辑:

创建此数组后,我想知道如何使用它以数组描述的方式遍历相同格式的对象。例如

function iterateAnotherObjectWithSameFormat(aObj) {
  for (var i = 0; i < arr.length; i++) {
    // access aObj['a'], then aObj['a.b'], then aObj['a.b.c'], etc..
  }
}

您可以采用递归方法,其中单个调用迭代属性并将键放入数组中。Thn 使用实际值和具有访问过的键的数组再次调用函数,直到找不到其他对象。

function flatKeys(object) {
    function iter(part, keys) {
        Object.keys(part).forEach(function (k) {
            var allKeys = keys.concat(k);
            flat.push(allKeys.join('.'));
            if (part[k] !== null && !Array.isArray(part[k]) && typeof part[k] === 'object') {
                iter(part[k], allKeys);
            }
        });
    }
    var flat = [];
    iter(object, []);
    return flat;
}
function getValue(object, path) {
    return path.split('.').reduce(function (r, a) {
        return (r || {})[a];
    }, object);
}
var object = { 'a': { 'b': { 'c': 1, 'd': 2 }, 'e': 3 }, 'f': 4, 'g': 5 },
    keys = flatKeys(object)
console.log(keys);
keys.forEach(function (a) {
    console.log(a, getValue(object, a));
});

平面对象

function flatKeys(object) {
    function iter(part, keys) {
        Object.keys(part).forEach(function (k) {
            var allKeys = keys.concat(k);
            flat[keys.concat(k).join('.')] = part[k];
            if (part[k] !== null && !Array.isArray(part[k]) && typeof part[k] === 'object') {
                iter(part[k], keys.concat(k));
            }
        });
    }
    var flat = {};
    iter(object, []);
    return flat;
}
var object = { 'a': { 'b': { 'c': 1, 'd': 2 }, 'e': 3 }, 'f': 4, 'g': 5 },
    flat = flatKeys(object);
console.log(flat);

遇到的每个属性名称都将以属性链上的键为前缀,并添加到数组中。

搜索将继续,直到处理完所有嵌套对象。

function findKeys(object, prefix) {
  prefix = (typeof prefix !== 'undefined') ? (prefix + '.') : '';
  var keys = [];
  Object.keys(object).forEach(function(key) {
    keys.push(prefix + key);
    if (typeof object[key] === 'object' && object[key] !== null && !Array.isArray(object[key]))
      keys = keys.concat(findKeys(object[key], prefix + key));
  });
  return keys;
};
console.log( findKeys({ 'a': { 'b': { 'c': 1, 'd': 2 }, 'e': 3 }, 'f': 4, 'g': 5 }) );

如果要访问具有变量名称的对象属性,则必须使用括号表示法。

但是,不能使用字符串访问嵌套属性。无论点如何,字符串都被视为普通属性名称。

您需要自己解析字符串。幸运的是,reduce非常简单。

var object = {
  'a': {
    'b': 5
  },
  'a.b': 10
};
var property = 'a.b';
console.log(object[property]);                            // 10
console.log(getNestedPropertyValue(object, property));    // 5
function getNestedPropertyValue(object, nestedProperty) {
  return nestedProperty.split('.').reduce(function(object, property) {
    return object[property];
  }, object);
}

下面是一个完整的示例:

function findKeys(object, prefix) {
  prefix = (typeof prefix !== 'undefined') ? (prefix + '.') : '';
  var keys = [];
  Object.keys(object).forEach(function(key) {
    keys.push(prefix + key);
    if (typeof object[key] === 'object' && object[key] !== null && !Array.isArray(object[key]))
      keys = keys.concat(findKeys(object[key], prefix + key));
  });
  return keys;
};
var obj1 = { 'a': { 'b': { 'c': 1, 'd': 2 }, 'e': 3 }, 'f': 4, 'g': 5 };
var obj2 = { 'a': { 'b': { 'c': 111, 'd': 222 }, 'e': 333 }, 'f': 444, 'g': 555 };
var arr = findKeys(obj1);
var iterateAnotherObjectWithSameFormat = (function() {
  function getNestedPropertyValue(object, nestedProperty) {
    return nestedProperty.split('.').reduce(function(object, property) {
      return object[property];
    }, object);
  }
  return function(object, keys, callback) {
    keys.forEach(function(key) {
      callback(getNestedPropertyValue(object, key));
    });
  };
}());
iterateAnotherObjectWithSameFormat(obj2, arr, function(value) {
  console.log(value);
});

最新更新