假设我有一个下面的物体:
{
"schema": [
{
"field": "name",
"type": "String",
"enabled": true
},
{
"field": "age",
"type": "Int",
"enabled": false
},
{
"field": "modelObj",
"type": "object",
"enabled": true,
"stuff": [
{
"name": "mod1",
"type": "array",
"enabled": true
},
{
"name": "mod2",
"type": "String",
"enabled": false
},
{
"name": "mod3",
"type": "array",
"enabled": true
}
]
},
{
"name": "modelArr",
"type": "array",
"enabled": false,
"elements": {
"elementsType": "String"
}
},
{
"name": "modelsNestedArr",
"type": "array",
"enabled": true,
"elements": {
"elementsType": "object"
},
"stuff": [
{
"name": "name",
"type": "String",
"enabled": true
},
{
"name": "models",
"type": "array",
"enabled": false,
"elements": {
"elementsType": "String"
}
}
]
}
]
}
我要递归地遍历此对象,并根据“ enabled”是否为false删除该项目。
所以预期的输出是:
[
{
"field": "name",
"type": "String",
"enabled": true
},
{
"field": "modelObj",
"type": "object",
"enabled": true,
"stuff": [
{
"name": "mod1",
"type": "array",
"enabled": true
},
{
"name": "mod3",
"type": "array",
"enabled": true
}
]
},
{
"name": "modelsNestedArr",
"type": "array",
"enabled": true,
"elements": {
"elementsType": "object"
},
"stuff": [
{
"name": "name",
"type": "String",
"enabled": true
}
]
}
]
我写了如下代码:
function r(a){
for (i = a.length - 1; i >= 0; --i) {
if(!a[i].enabled){
a.splice(i,1)
} else if (a[i].enabled){
if(a[i].type == "object"){
if(a[i]){
a[i].stuff= r(a[i].stuff)
}
} else if (a[i].type == "array"){
if(a[i].hasOwnProperty("elements") && a[i].elements.elementsType== "object"){
a[i].stuff= r(a[i].stuff)
}
}
}
}
return a
}
var final = r(a.schema)
console.log(JSON.stringify(final))
但是,我得到以下输出:
错误输出:
[
{
"field": "name",
"type": "String",
"enabled": true
},
{
"field": "age",
"type": "Int",
"enabled": false
},
{
"field": "modelObj",
"type": "object",
"enabled": true,
"stuff": [
{
"name": "mod1",
"type": "array",
"enabled": true
},
{
"name": "mod2",
"type": "String",
"enabled": false
},
{
"name": "mod3",
"type": "array",
"enabled": true
}
]
},
{
"name": "modelArr",
"type": "array",
"enabled": false,
"elements": {
"elementsType": "String"
}
},
{
"name": "modelsNestedArr",
"type": "array",
"enabled": true,
"elements": {
"elementsType": "object"
},
"stuff": [
{
"name": "name",
"type": "String",
"enabled": true
}
]
}
]
我到底在做错什么吗?
答案 0 :(得分:2)
使用.map()和.filter()的递归函数将使您的生活更轻松:
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
void main() => runApp(SnackBarDemo());
class SnackBarDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'SnackBar Demo',
home: CupertinoPageScaffold(
child: SnackBarPage(),
),
);
}
}
class SnackBarPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: SnackBarBody(),
);
}
}
class SnackBarBody extends StatefulWidget {
SnackBarBody({Key key,}):
super(key: key);
@override
_SnackBarBodyState createState() => new _SnackBarBodyState();
}
class _SnackBarBodyState extends State<SnackBarBody> {
@override
Widget build(BuildContext context) {
return Center(
child: RaisedButton(
onPressed: () {
final snackBar = SnackBar(content: Text('Yay! A SnackBar!'),action: SnackBarAction(label: 'Undo',
onPressed: () {
// Some code to undo the change!
},
),
);
// Find the Scaffold in the Widget tree and use it to show a SnackBar!
Scaffold.of(context).showSnackBar(snackBar);
},
child: Text('Show SnackBar'),
),
);
}
}
这将适用于任何深度。
它确实假定您的所有数组都在 function isEnabledRecursive(data){
return data.filter(
item=>item.enabled
)
.map(
item=>item.stuff?Object.assign(item,{stuff:isEnabledRecursive(item.stuff)})
:item
);
}
const dataWithFilteredSchema = Object.assign(data, {schema:isEnabledRecursive(data.schema)})
属性中。如果您有其他带有对象数组的属性,则必须使用stuff
之类的属性遍历每个属性,以查看它们中是否包含数组。
至于为什么您的原始代码无法正常工作,如果语句正在运行,您的其他代码就什么也没有。当您说for(property of item)
或a[i].type
时,它是未定义的。您可能想说a[i].dataType
和typeof a[i] === "object"
答案 1 :(得分:1)
根据我的观察,您的架构对象不一致或函数。 您的架构对象具有 type 和 dataType 键。我正在考虑将其全部视为类型,这是解决方案。
在您的splice实现中,数组在循环中发生了变化,可能会跳过一些索引。
例如如果数组是
[
{name: 'mod1', enabled: false},
{name: 'mod2', enabled: true},
{name: 'mod3', enabled: true}
]
删除索引0后,数组长度变为2而不是3。因此,将少访问一个元素。
因此,我包含了另一个对象 deleteIndices ,以在循环完成后标记要删除的索引。
顺便说一句,您始终可以选择地图和过滤器以这种方式 更简单。
function r(a) {
let deleteIndices = {};
for (let i = 0; i < a.length; i++) {
if (!a[i].enabled) {
deleteIndices[i] = true;
} else {
if (a[i].type == "object") {
a[i].stuff = r(a[i].stuff)
} else if (a[i].type == "array" && a[i].elements && a[i].elements.elementsType == "object") {
a[i].stuff = r(a[i].stuff)
}
}
}
a = a.filter((e, index) => !deleteIndices[index])
return a;
}
schema = r(schema)
答案 2 :(得分:0)
让我们以 a 的名称命名您的数组(object.schema),然后可以像这样获得结果:
var result = a.filter(element => element.enabled).map(element => {
if ((element.dataType == "object" || element.type == "array") && element.stuff && element.stuff.length > 0) {
element.stuff = element.stuff.filter(st => st.enabled);
}
return element;
});
请注意,有时您有dataType,有时您有类型作为字段名称。
您应该使用地图和过滤器。 编写和使用非常简单。
答案 3 :(得分:0)
我能想到的最简单,最贴心的解决方案,它将在任何深度都适用
function r(arr){
let filtered = arr.filter((obj)=>{
return obj.enabled;
});
return filtered.map((obj)=>{
if(obj.stuff)
obj.stuff = r(obj.stuff)
return obj
})
}
result = r(a.schema)
console.log(JSON.stringify(result,null,2))