【问题标题】:How to convert a nested JavaScript object to a flat array?如何将嵌套的 JavaScript 对象转换为平面数组?
【发布时间】:2016-11-16 16:34:21
【问题描述】:

我已经在这个解决方案上编写了几个小时,但似乎无法再取得太大进展。这是一个很难编写的函数。这是我的意见:

var testObj = {
  'b': 'num',
  'a': {
    'd': 'num',
    'c': 'num'
  },
  'g': ['num', 'num', {
    'x': 'num',
    'y': 'num'
  }],
  'e': 'num'
};

这是我试图从上面生成的输出:

var flatTestObj = [
  ['b', 'num'],
  ['a', 'obj'],
  ['a', 'obj', 'd', 'num'],
  ['a', 'obj', 'c', 'num'],
  ['g', 'arr'],
  ['g', 'arr', 0, 'num'],
  ['g', 'arr', 1, 'num'],
  ['g', 'arr', 2, 'obj'],
  ['g', 'arr', 2, 'obj', 'x', 'num'],
  ['g', 'arr', 2, 'obj', 'y', 'num'],
  ['e', 'num']
];

(稍后我也会按字母顺序排列键,但我可以自己处理这部分,所以我将其排除在问题之外以便更容易回答)但是是的,重点是保证对象的相同顺序遍历以后会采用这种格式。

基本上,让它递归地遍历对象并将每个键/索引映射作为一个新元素添加到flatTestObj,以便稍后您可以遍历flatTestObj并通过引用来自testObj的每个其他元素来获取每个成员当前的flatTestObj 索引数组值。

这是我目前所拥有的,但我很难让它与嵌套一起工作:

var flattened = [];

function flatten(json, acc) {
  var keys = Object.keys(json);

  for (var i = 0; i < keys.length; i++) {
    var key = keys[i];
    var val = json[key];

    var strVal = typeof val === 'object' ? 'obj' : val;

    if (acc.length === 0) {
      acc = [key, strVal];
    } else {
      acc = acc.concat([key, strVal]);
    }

    if (typeof val === 'object') {
      flatten(val, acc);
    } else {
      flattened.push(acc);
      acc = [];
    }
  }
}

flatten(testObj, []);

【问题讨论】:

    标签: javascript arrays json algorithm flatten


    【解决方案1】:

    这给出了您正在寻找的输出:

    var flattened = [];
    function flatten(json, acc, inArray) {
      var key;
    
      acc = acc || [];
      for(key in json) {
        if(inArray) {
          key = +key;  //coerce to number
        }
        if(json[key] instanceof Array) {
          flattened.push(acc.concat([key, 'arr']));
          flatten(json[key], acc.concat([key, 'arr']), true);
        }
        else if(json[key] instanceof Object) {
          flattened.push(acc.concat([key, 'obj']));
          flatten(json[key], acc.concat([key, 'obj']));
        }
        else {
          flattened.push(acc.concat(key, json[key]));
        }
      }
    } //flatten
    

    基本上,每次推送到flattened 数组时都需要包含acc.concat()

    var testObj = {
      'b': 'num',
      'a': {
        'd': 'num',
        'c': 'num'
      },
      'g': ['num', 'num', {
        'x': 'num',
        'y': 'num'
      }],
      'e': 'num'
    };
    
    var flattened = [];
    function flatten(json, acc, inArray) {
      var key;
      
      acc = acc || [];
      for(key in json) {
        if(inArray) {
          key = +key;  //coerce to number
        }
        if(json[key] instanceof Array) {
          flattened.push(acc.concat([key, 'arr']));
          flatten(json[key], acc.concat([key, 'arr']), true);
        }
        else if(json[key] instanceof Object) {
          flattened.push(acc.concat([key, 'obj']));
          flatten(json[key], acc.concat([key, 'obj']));
        }
        else {
          flattened.push(acc.concat(key, json[key]));
        }
      }
    } //flatten
    
    flatten(testObj);
    console.log(JSON.stringify(flattened));

    【讨论】:

    • 漂亮!也很简单!太感谢了!我要研究一段时间,但它看起来很完美!除了数组索引被设置为扁平数组中的字符串,但我想我可以弄清楚如何解决这个问题。
    【解决方案2】:

    这是使用递归函数调用的一种方法

    var testObj = {
        'b': 'num',
        'a': {
            'd': 'num',
            'c': 'num'
        },
        'g': ['num', 'num', {
            'x': 'num',
            'y': 'num'
        }],
        'e': 'num'
    };
    
    var flatTestObj = (function it(what, arr, chain) {
        if (typeof what === "object") {
            var fn = function(k) {
                var type = Array.isArray(what[k]) ? 'arr' : 'obj' ,
                	vArr = [k, typeof what[k] === "object" ? type : what[k]],
                    fArr = chain.concat(vArr);
                                
                arr.push(fArr); 
                it(what[k], arr, fArr);
            }
    
        	if (Array.isArray(what)) for (var i in what) fn(i)
            else Object.keys(what).forEach(fn);
        }
        return arr;
    })(testObj, [], []);
    
    document.body.innerHTML = '<pre>' + JSON.stringify(flatTestObj, 0, 4) + '</pre>';

    【讨论】:

    • Eeek,好像有人在你做这个的时候回答了这个问题。希望它可以帮助某人。无论如何我都支持你!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-14
    • 2020-01-15
    • 1970-01-01
    • 2016-04-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多