【问题标题】:javascript filter nested object based on key valuejavascript 根据键值过滤嵌套对象
【发布时间】:2012-11-15 22:57:21
【问题描述】:

我希望通过“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)});

这只是返回未修改的嵌套对象,即使我将过滤器的值设置为 1。 .filter 是否适用于嵌套对象,或者我是否需要在这里滚动我自己的函数,建议并更正代码。 cjm

【问题讨论】:

    标签: javascript filter nested


    【解决方案1】:

    递归过滤函数很容易创建。这是一个示例,它剥离了一个 JS 对象中定义的所有 ["depth","x","x0","y","y0","parent","size"] 项:

    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;
    }
    

    如果您想通过其他方式进行过滤,只需使用您选择的过滤功能更新第二行即可。

    【讨论】:

      【解决方案2】:

      这是过滤嵌套数组的函数:

      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: [...] },
              ...
          ] },
          ...
      ]
      

      其中 <...> 代表一些属性(在您的情况下是“名称”、“步骤”和“id”),而“孩子”是可选的服务属性。 现在您可以将包装的对象与条件回调一起传递给过滤器函数:

      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)
      

      代码示例可能并不理想,但可能会将某人推向正确的方向。

      【讨论】:

        【解决方案3】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2022-01-20
          • 1970-01-01
          • 1970-01-01
          • 2019-08-10
          • 1970-01-01
          • 2020-03-11
          • 1970-01-01
          • 2021-01-15
          相关资源
          最近更新 更多