【问题标题】:Filter JSON data with recursive parent-child relationship过滤具有递归父子关系的 JSON 数据
【发布时间】:2020-11-20 16:53:34
【问题描述】:

我有一个 JSON 父子递归结构,如下例所示。

如何过滤此 JSON 列表以仅排除与所选索引对应的对象?

 familyTree =[
  {
    name: "parent",
    index:"0",
    age:"50,
    children: [
         {
            name: "first child",
            index:"0.0",
            age:"30",
            children: [
                {
                    name: "first grandChild",
                    index:"0.0.0",
                    age:"5"
                },
                {
                    name: "second grandChild",
                    index: "0.0.1",
                    age:"2"
                }
            ]
         },
         {
            name: "second child",
            index:"0.1",
            age:"24",
         }
    ]
 }
]

例如如果我想排除索引为 "0.0.1" 的元素,我的结果将是:

 familyTree =[
   {
    name: "parent",
    index:"0",
    children: [
         {
            name: "first child",
            index:"0.0",
            age:"30",
            children: [
                {
                    name: "first grandChild",
                    index:"0.0.0",
                    age:"5"
                }
            ]
         },
         {
            name: "second child",
            index:"0.1",
            age:"24",
         }
    ]
 }
]

我尝试过使用 ES6 函数 filter() 但它可能是错误的用法,因为它不起作用

     const elemToRemove= familyTree[0].children[0].children[1]; //index: 0.0.1
     familyTree.filter(
        (elem) => JSON.stringify(elem) === JSON.stringify(elemToRemove)
     );

感谢您的帮助

【问题讨论】:

  • 但您的结果中仍然包含索引为 0.0.1 的元素?
  • 我的错,我会编辑问题
  • 您会一直使用index 或任何键进行过滤吗?
  • 总是按索引
  • 没有 JSON 数组这样的东西。 JSON 始终是一个字符串。你有一个对象数组。

标签: javascript json object ecmascript-6


【解决方案1】:

这是解决您的问题的方法。 familyTreeFilterChildrenByIndex 函数检查每个元素的索引,并在任何子元素上运行。

const familyTree =[ { name: "parent", index:"0", age:"50", children: [ { name: "first child", index:"0.0", age:"30", children: [ { name: "first grandChild", index:"0.0.0", age:"5" }, { name: "second grandChild", index: "0.0.1", age:"2" } ] }, { name: "second child", index:"0.1", age:"24", } ] } ]

const familyTreeFilterChildrenByIndex = function (familyTree, indexToRemove) {
  const result = []
  for (const parent of familyTree) {
    if (parent.index === indexToRemove) {
      continue
    } else if (parent.children) {
      result.push({
        ...parent,
        children: familyTreeFilterChildrenByIndex(parent.children, indexToRemove),
      })
    } else {
      result.push(parent)
    }
  }
  return result
}

console.log((familyTreeFilterChildrenByIndex(familyTree, '0.0.1')))

【讨论】:

    【解决方案2】:

    这是filterRec 的一种可能实现-

    function filterRec (t, f)
    { const many = (t = []) =>
        t.flatMap(one)
    
      const one = (t = {}) =>
        Boolean(f(t))
          ? [ { ...t, children: many(t.children) } ]
          : []
      
      return many(t)
    }
    

    用法类似于Array.prototype.filter-

    const result =
      filterRec(familyTree, elem => elem.index !== "0.0.1")
      
    console.log(JSON.stringify(result, null, 2))
    
    [
      {
        "name": "parent",
        "index": "0",
        "age": "50",
        "children": [
          {
            "name": "first child",
            "index": "0.0",
            "age": "30",
            "children": [
              {
                "name": "first grandChild",
                "index": "0.0.0",
                "age": "5",
                "children": []
              }
            ]
          },
          {
            "name": "second child",
            "index": "0.1",
            "age": "24",
            "children": []
          }
        ]
      }
    ]
    

    展开下面的sn-p,在自己的浏览器中验证结果-

    function filterRec (t, f)
    { const many = (t = []) =>
        t.flatMap(one)
    
      const one = (t = {}) =>
        Boolean(f(t))
          ? [ { ...t, children: many(t.children) } ]
          : []
      
      return many(t)
    }
    
    const familyTree =
      [{name:"parent",index:"0",age:"50",children:[{name:"first child",index:"0.0",age:"30",children:[{name:"first grandChild",index:"0.0.0",age:"5"},{name:"second grandChild",index:"0.0.1",age:"2"}]},{name:"second child",index:"0.1",age:"24"}]}]
      
    const result =
      filterRec(familyTree, elem => elem.index !== "0.0.1")
      
    console.log(JSON.stringify(result, null, 2))

    【讨论】:

      【解决方案3】:

      如果您总是通过索引访问/删除元素,您可以将其用作访问该项目的地址,并在删除它的同时返回它。此解决方案在原地编辑原始数组。

      const indexToRemove = '0.0.1';
      const keys = indexToRemove.split('.').map((e, i, a) => a.slice(0, i+1).join('.'));
      // ['0', '0.0', '0.0.1']
      
      const removedItem = keys.reduce((a, k, i) => {
        if (i !== keys.length-1) {
          a = a.find(e => e.index === k).children;
        } else {
          const ri = a.map(e => e.index).indexOf(k);
          a = a.splice(ri, 1);
        }
        return a;
      }, familyTree);
      

      const familyTree =[
        {
          name: "parent",
          index:"0",
          age:"50",
          children: [
               {
                  name: "first child",
                  index:"0.0",
                  age:"30",
                  children: [
                      {
                          name: "first grandChild",
                          index:"0.0.0",
                          age:"5"
                      },
                      {
                          name: "second grandChild",
                          index: "0.0.1",
                          age:"2"
                      }
                  ]
               },
               {
                  name: "second child",
                  index:"0.1",
                  age:"24",
               }
          ]
       }
      ]
      
      const indexToRemove = '0.0.1';
      const keys = indexToRemove.split('.').map((e, i, a) => a.slice(0, i+1).join('.'));
      
      const removedItem = keys.reduce((a, k, i) => {
        if (i !== keys.length-1) {
          a = a.find(e => e.index === k).children;
        } else {
          const ri = a.map(e => e.index).indexOf(k);
          a = a.splice(ri, 1);
        }
        return a;
      }, familyTree);
      
      console.log(removedItem);
      console.log(familyTree);

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-10-24
        • 2022-11-14
        • 2020-10-11
        • 2017-02-26
        • 1970-01-01
        相关资源
        最近更新 更多