javascript根据键值过滤嵌套对象

时间:2012-11-15 22:57:22

标签: javascript filter nested

我希望通过“step”键的值过滤嵌套的javascript对象:

var data = {
"name": "Root",
"step": 1,
"id": "0.0",   
"children": [
    {
    "name": "first level child 1",
    "id": "0.1",
    "step":2,
    "children": [
        {
        "name": "second level child 1",
        "id": "0.1.1",
        "step": 3,
        "children": [
            {
            "name": "third level child 1",
            "id": "0.1.1.1",
            "step": 4,
            "children": []},
        {
            "name": "third level child 2",
            "id": "0.1.1.2",
            "step": 5,
            "children": []}

        ]},
                ]}
]

};

var subdata = data.children.filter(function (d) {
        return (d.step <= 2)});

这只返回未修改的嵌套对象,即使我将filter的值设置为1。 .filter是否可以处理嵌套对象,或者我需要在这里滚动自己的函数,建议并更正代码。 CJM

3 个答案:

答案 0 :(得分:1)

递归过滤器功能相当容易创建。这是一个示例,它剥离了定义为["depth","x","x0","y","y0","parent","size"]的所有项目的JS对象:

function filter(data) {
  for(var i in data){
    if(["depth","x","x0","y","y0","parent","size"].indexOf(i) != -1){
       delete data[i]; 
    } else if (i === "children") {
      for (var j in data.children) {
        data.children[j] = filter(data.children[j])
      }
    }  
  }
  return data;
}

如果您想过滤其他内容,只需使用您选择的过滤功能更新第二行。

答案 1 :(得分:1)

这是过滤嵌套数组的功能:

const filter = arr => condition => {
    const res = [];
    for (const item of arr) {
        if (condition(item)) {
            if (!item.children) {
                res.push({ ...item });
            } else {
                const children = filter(item.children)(condition);
                res.push({ ...item, children })
            }
        }
    }
    return res;
}

您唯一需要做的就是将根对象包装成数组以达到自相似性。通常,您的输入数组应如下所示:

data = [
    { <...>, children: [
        { <...>, children: [...] },
        ...
    ] },
    ...
]

其中&lt; ...&gt;代表一些属性(在您的情况下是“name”,“step”和“id”),“children”是可选的服务属性。 现在,您可以将包装对象与条件回调一起传递到过滤器函数中:

filter(data)(item => item.step <= 2)

你会得到你的结构过滤。 这里有一些函数来处理我刚编写的有趣的结构:

const map = arr => f => {
    const res = [];
    for (const item of arr) {
        if (!item.children) {
            res.push({ ...f({ ...item }) });
        } else {
            res.push({ ...f({ ...item }), children: map(item.children)(f) });
        }
    }
    return res;
}

const reduce = arr => g => init => {
    if (!arr) return undefined;
    let res = init;
    for (const item of arr) {
        if (!item.children) {
            res = g(res)({ ...item });
        } else {
            res = g(res)({ ...item });
            res = reduce(item.children)(g)(res);
        }
    }
    return res;
}

用法示例:

map(data)(item => ({ step: item.step }))
reduce(data)($ => item => $ + item.step)(0)

可能代码示例并不理想,但可能会让某人朝着正确的方向前进。

答案 2 :(得分:-1)

是的,filter适用于一个数组(列表),就像一个节点的子节点一样。你有一棵树,如果你想搜索整个树,你需要使用tree traversal algorithm,或者你首先将所有节点放入一个可以过滤的数组中。我相信你可以自己编写代码。