如何将嵌套的 JavaScript 对象转换为平面数组?
How to convert a nested JavaScript object to a flat array?
我已经用这个解决方案编写了几个小时的代码,但似乎无法再取得太大进展。这是一个非常难写的函数。这是我的输入:
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']
];
(稍后我也会按字母顺序排列键,但我可以自己处理这部分,所以我将其从问题中排除以使其更容易回答)但是是的,重点是保证相同的顺序遍历以后这种格式的对象。
基本上,让它递归地遍历对象并将每个 key/index 映射作为新元素添加到 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, []);
这给出了您正在寻找的输出:
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));
这是使用递归函数调用的一种方法
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>';
我已经用这个解决方案编写了几个小时的代码,但似乎无法再取得太大进展。这是一个非常难写的函数。这是我的输入:
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']
];
(稍后我也会按字母顺序排列键,但我可以自己处理这部分,所以我将其从问题中排除以使其更容易回答)但是是的,重点是保证相同的顺序遍历以后这种格式的对象。
基本上,让它递归地遍历对象并将每个 key/index 映射作为新元素添加到 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, []);
这给出了您正在寻找的输出:
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));
这是使用递归函数调用的一种方法
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>';