在javascript中展平嵌套对象/数组
我是Javascript新手,我有嵌套的对象和数组,我想将它们展平 我有在javascript中展平嵌套对象/数组,javascript,arrays,object,nested,Javascript,Arrays,Object,Nested,我是Javascript新手,我有嵌套的对象和数组,我想将它们展平 我有 [{a:2,b:[{c:3,d:[{e:4,f:5},{e:5,f:6}], {c:4,d:[{e:7,f:8}]} ] }] 我想 [{a:2,c:3,e:4,f:5}, {a:2,c:3,e:5,f:6}, {a:2,c:4,e:7,f:8}] 我试图为数组中的一个对象修改以下函数,但我只得到数组中的最后一个对象[{a:2,c:4,e:7,f:8}]。我想我的问题是知道如何迭代数组和对象 原文: function
[{a:2,b:[{c:3,d:[{e:4,f:5},{e:5,f:6}],
{c:4,d:[{e:7,f:8}]}
]
}]
我想
[{a:2,c:3,e:4,f:5}, {a:2,c:3,e:5,f:6}, {a:2,c:4,e:7,f:8}]
我试图为数组中的一个对象修改以下函数,但我只得到数组中的最后一个对象[{a:2,c:4,e:7,f:8}]。我想我的问题是知道如何迭代数组和对象
原文:
function flatten(obj) {
var flattenedObj = {};
Object.keys(obj).forEach(function(key){
if (typeof obj[key] === 'object') {
$.extend(flattenedObj, flatten(obj[key]));
} else {
flattenedObj[key] = obj[key];
}
});
return flattenedObj;
}
我的脚本(两者的结果相同):
感谢您的帮助我建议从更简单的数据对象开始测试您的函数,然后逐步添加更复杂的对象,直到您的函数按预期执行。弗雷奇 在这里,您可以看到我是如何从一个简单的
test1
对象开始的,然后是test2
等等,以便将逻辑分解为更小的增量
为了删除我们以前的重复项,我必须抛出一个错误来打破递归的forEach循环,这增加了不必要的重复“行”-也许最好使用一个普通的for
循环,你可以简单地打破它代码>然后对实际错误使用错误处理
递归函数的基本思想是检查对象的类型(数组或对象),然后通过循环添加值,但需要对这些对象进行另一次检查,以查看它们是否为数组和对象,如果是,则再次调用该函数。当发现重复的键时,即{c:3},请删除当前键并添加新键,然后继续循环
如果您有更多的示例数据,您可以添加更多的测试,但是有更好的库可以帮助您进行TDD(测试驱动开发)
常数isArray=(arr)=>{
返回数组.isArray(arr);
};
常量等对象=(对象)=>{
返回对象的类型==“对象”&&obj!==null;
};
常数展平=(树、行、结果)=>{
试一试{
if(isArray(tree)){
tree.forEach((分支,索引)=>{
展平(分支、行、结果);
});
}else if(对象(树)){
Object.keys(树).forEach((键)=>{
//我们不想向行中添加对象或数组-
如果(!isArray(tree[key])&&!isObject(tree[key])){
如果(输入行){
//检测到新行,获取要使用的现有键
让keysArray=Object.keys(行);
//我们将向后循环并删除重复的键
让end=Object.keys(row).length;
让stopAt=Object.keys(行).indexOf(键);
//将对象键从对象背面删除到新找到的对象键
对于(设z=end;z>stopAt;z--){
删除行[keysArray[z-1]];
}
行[键]=树[键];
}否则{
行[键]=树[键];
}
}否则{
展平(树[键]、行、结果);
抛出“跳过”;
}
});
//如果不字符串化,结果中的所有其他行都将被覆盖
push(JSON.stringify(row));
}
}捕获(e){
//控制台日志(e)
}最后{
返回result.map((行)=>JSON.parse(行));
}
};
///测验
常数test1=[
{
答:2,,
b:3,
},
];
常数expected1=[{a:2,b:3}];
常数test2=[
{
答:2,,
b:[
{
c:3,
},
],
},
];
常数expected2=[{a:2,c:3}];
常数test3=[
{
答:2,,
b:[
{
c:3,
},
{c:4},
{c:5},
],
},
];
预期常数3=[
{a:2,c:3},
{a:2,c:4},
{a:2,c:5},
];
设test4=[
{
答:2,,
b:[
{
c:3,
d:[
{e:4,f:5},
{e:5,f:6},
],
},
{c:4,d:[{e:7,f:8}]},
],
},
];
预期常数4=[
{a:2,c:3,e:4,f:5},
{a:2,c:3,e:5,f:6},
{a:2,c:4,e:7,f:8},
];
常量测试=(名称、分辨率、预期值)=>{
console.log(
`${name}传递了${JSON.stringify(res)==JSON.stringify(预期)}`
);
//console.log(res,预期);
};
//test(“test1”,展平(test1,{},[]),预期为1;
//test(“test2”,展平(test2,{},[]),预期为2;
//test(“test3”,展平(test3,{},[]),预期为3;
test(“test4”,展平(test4,{},[]),预期为4;
这是一个有点庞然大物,它不保留键的顺序,但它可以在没有重复项的情况下工作
它是递归的,所以要注意调用堆栈
- 首先,循环遍历数组中的项
- 如果项是数组,则进行递归调用。
- 从该调用返回时,如果返回的对象数量超过最终结果中当前的数量,则使用最终结果中对象的属性更新返回的对象,小心避免覆盖先前存在的属性
- 否则,使用返回结果中的属性更新最终结果,再次注意不要覆盖现有属性
- 如果该项不是数组
- 如果这是第一项,则将其放入最终结果中
- 否则,将项目的属性添加到最终结果中的所有项目中,而不覆盖任何属性
函数makeFlat(arr)//假设您总是传入一个数组
{
让对象=[];
arr.forEach(项目=>
{
让currentObject={};
常量键=对象键(项);
keys.forEach(key=>
{
const obj=项[键];
if(数组isArray(obj))
{
let parts=makeFlat(obj);
如果(objects.length>0)
{
如果(parts.length>objects.length)
{
parts.forEach(part=>
{
目标
flat_array=[];
function superflat(array){
for (var i = 0; i < array.length; i++) {
var obj = array[i]
var flattenedObj = {};
Object.keys(obj).forEach(function(key){
if (typeof obj[key] === 'object') {
$.extend(flattenedObj, flatten(obj[key]));
} else {
flattenedObj[key] = obj[key];
}
});
flat_array.push(flattenedObj);
}
};
mega_flat_array=[];
function megaflatten(obj) {
Object.keys(obj).forEach(function(key){
var flattenedObj = {};
if (typeof obj[key] === 'object') {
$.extend(flattenedObj, flatten(obj[key]));
} else {
flattenedObj[key] = obj[key];
}
mega_flat_array.push(flattenedObj);
});
}