以递归方式编辑属性名称

时间:2015-04-23 15:21:08

标签: javascript recursion

我有一个来自JSON的JS数据结构,如下所示:

[
    {
        "eid": "T1",
        "name": "Topic1",
        "children": [
            {
                "eId": "T1.1",
                "name": "subtopic1",
                "children": []
            },
            {
                "eId": "T1.2",
                "name": "subtopic2"
            }
        ]
    },
    {
        "eId": "T2",
        "name": "Topic1",
        "children": []
    }
]

我需要迭代这个并构建另一个看起来像这样的结构:

[
    {
        "id": "T1",
        "text": "Topic1",
        "children": [
            {
                "id": "T1.1",
                "text": "subtopic1",
                "children": []
            },
            {
                "id": "T1.2",
                "text": "subtopic2"
            }
        ]
    },
    {
        "id": "T2",
        "text": "Topic1",
        "children": []
    }
]

我的代码在这里

// topics = the first strucutre

var treeData=[]; 
for(var i=0,len=topics.length;i<len;++i)
{
    var topicElements=topics[i];
    var subNodes=[];
    var nodes={};
    nodes['id']=topicElements.eId;
    nodes['text']=topicElements.name;

    for (var j =0;j<topicElements.children.length;++j)
        {
            nodesChildren = topicElements.children;
            position = subNodes.length;
            subNodes[position] = new Object();
            subNodes[position]['id']=nodesChildren[j].eId;
            subNodes[position]['text']=nodesChildren[j].name;
        }
    nodes['children']=subNodes;
    treeData.push(nodes);
}

它适用于一个级别,但如果我必须遍历T1.1的子级,那么它将无法工作。你能建议我采用递归方式吗?

3 个答案:

答案 0 :(得分:1)

这样的事情可能是:

function redefineData(data) {
    var outData = [];
    for (var i = 0; i < data.length; i++) {
        var obj = { id: data[i].eid, text: data[i].name };
        if (data[i].children && data[i].children.length) {
            obj.children = redefineData(data[i].children);
        }
        outData.push(obj);
    }
    return outData;
}

var treeData = redefineData(topics);

答案 1 :(得分:0)

这是ES6中的通用版本,我认为它更简单:

const renameKey = (oldName, newName) => (xs) =>
  xs .map (({[oldName]: old, children, ...rest}) => ({
    [newName]: old,
    ...rest,
    ...(children ? {children: renameKey (oldName, newName) (children)} : {})
  }))

const fixId = renameKey ('eId', 'id')


const data = [{eId: "T1", name: "Topic1", children: [{eId: "T1.1", name: "subtopic1", children: []}, {eId: "T1.2", name: "subtopic2"}]}, {eId: "T2", name: "Topic1", children: []}]

const treeData = fixId (data)

console .log (treeData)

如果您不介意将空children数组添加到没有数组的数组中,则可以简化一下:

const renameKey = (oldName, newName) => (xs) =>
  xs .map (({[oldName]: old, children, ...rest}) => ({
    [newName]: old,
    ...rest,
    children: renameKey (oldName, newName) (children || [])
  }))

如果样本数据没有错字,并且您实际上需要将eIdeid都更改为id,则可以两次调用它,每次拼写一次。但是,如果您想完全忽略大小写,则需要使用不同的技术(...如果您拥有两个不区分大小写的不同键,也可能会导致问题。)

答案 2 :(得分:-1)

如果真的是“eid”和“eId”的所有实例(请注意,你在这里写了不同的案例!)键应该用“id”替换,所有“name”键都用“text”代替 - 只有这样 - 这个有点hacky方法可能会表现最佳,不经过任何递归循环:

var json = [ "your json code from above" ];
json = JSON.parse(JSON.stringify(json).replace(/"(eId|eid)":/g, '"id":').replace(/"name":/g, '"text":'));

如果差异"eid""eId"只是一种类型而且总是"eid",那么这就足够了:

var json = [ "your json code from above" ];
json = JSON.parse(JSON.stringify(json).replace(/"eid":/g, '"id":').replace(/"name":/g, '"text":'));