【问题标题】:Remove objects from a deeply nested object array by property value按属性值从深度嵌套的对象数组中删除对象
【发布时间】:2020-10-30 18:56:49
【问题描述】:

假设我有一个嵌套对象数组。一种可能的示例场景是:

content: [
    {
        prop1: someValue,
        prop2: someValue,
        content: [
            {
                prop2: someValue,
                prop3: someValue,
                myProperty: myValue
            },
            {
                prop1: someValue,
                prop3: someValue,
                myProperty: otherValue
            }
        ]
    },
    {
        prop5: someValue,
        prop2: someValue
    }
]

以下是可能性:

  • 结构以content[] 开头,但后代可能有也可能没有content 属性。
  • 层次结构的级别可以是任意数字。
  • 对象包含的属性并不总是相同,即一个对象可能具有 x、y、z 属性,而另一个对象可能具有 v、w、z 属性。
  • 如果层次结构中的任何对象具有myProperty 键,则不会有content 键。
  • 层次结构中的多个对象可以有myProperty,其值为'myValue

我的要求:

  • 如果对象在任何级别都具有属性 myProperty 且值为 myValue,则从层次结构中删除整个对象(不仅仅是属性)。

到目前为止我的尝试:

  private removeObjects(content: any, values: string[]): any {
    if (!content || content.length === 0) {
      return
    }
    content = content.filter((c) => {
      if (!c.myProperty) return true
      return c.myProperty.indexOf(values) > 0
    })
    // Here is my problem since I am supposed to do a recursive call on each of child contents,
    // how do I merge back the original array?
    return this.removeObjects(content, values)
  }

【问题讨论】:

    标签: javascript arrays typescript object filter


    【解决方案1】:

    使用递归方法,拥有filter 数组项及其content 数组。

    const filter = (arr, name, value) =>
      arr
        .filter((obj) => !(name in obj && obj[name] === value))
        .map((obj) => {
          const nObj = { ...obj };
          if (obj.content && Array.isArray(obj.content)) {
            nObj.content = filter(obj.content, name, value);
          }
          return nObj;
        });
        
    content = [
      {
        prop1: 'someValue',
        prop2: 'someValue',
        content: [
          {
            prop2: 'someValue',
            prop3: 'someValue',
            myProperty: 'myValue',
          },
          {
            prop1: 'someValue',
            prop3: 'someValue',
            myProperty: 'otherValue',
          },
        ],
      },
      {
        prop5: 'someValue',
        prop2: 'someValue',
      },
    ];
    
    
    
    const updated = filter(content, "myProperty", "myValue");
    
    console.log(updated);

    【讨论】:

      【解决方案2】:

      您可以使用以下函数来获得预期的结果:

      let data = {
          content: [
              {
                  prop1: 'someValue',
                  prop2: 'someValue',
                  content: [
                      {
                          prop2: 'someValue',
                          prop3: 'someValue',
                          myProperty: 'myValue'
                      },
                      {
                          prop1: 'someValue',
                          prop3: 'someValue',
                          myProperty: 'otherValue'
                      }
                  ]
              },
              {
                  prop5: 'someValue',
                  prop2: 'someValue'
              }
          ]
      }
      
      function removeMyvalyeObj(data) {
          for (let i = data.content.length - 1; i >= 0; i--) {
              if (data.content[i].myProperty === 'myValue') {
                  data.content.splice(i, 1);
              } else if(data.content[i].content) {
                  removeMyvalyeObj(data.content[i])
              }
          }
      }
      
      removeMyvalyeObj(data);
      console.log(data);
      

      【讨论】:

        【解决方案3】:

        以下递归返回一个新数组而不改变原始数组

        const content = [{
            prop1: "someValue",
            prop2: "someValue",
            content: [{
                prop2: "someValue",
                prop3: "someValue",
                myProperty: "myValue"
              },
              {
                prop1: "someValue",
                prop3: "someValue",
                myProperty: "otherValue"
              }
            ]
          },
          {
            prop5: "someValue",
            prop2: "someValue"
          }
        ]
        
        function removeObjects(content) {
          return content.reduce((arr, obj) => {
            if (obj["myProperty"] && obj["myProperty"] === "myValue") {
              return arr
            } else if (obj["content"] && obj["content"].length) {
              arr.push({ ...obj,
                content: removeObjects(obj["content"])
              })
              return arr
            } else {
              arr.push(obj);
              return arr;
            }
          }, []);
        }
        
        
        
        console.log(removeObjects(content))

        预期输出:

        const content = [{
                prop1: "someValue",
                prop2: "someValue",
                content: [
                  {
                    prop1: "someValue",
                    prop3: "someValue",
                    myProperty: "otherValue"
                  }
                ]
              },
              {
                prop5: "someValue",
                prop2: "someValue"
              }
            ]
        

        【讨论】:

          【解决方案4】:

          试试这个,(这是 JavaScript 版本)

              let someValue = 'a';
              let otherValue ='x';
              let myValue = 'xy';
              let content = [
                  {
                      prop1: someValue,
                      prop2: someValue,
                      content: [
                          {
                              prop2: someValue,
                              prop3: someValue,
                              myProperty: myValue
                          },
                          {
                              prop1: someValue,
                              prop3: someValue,
                              myProperty: otherValue
                          }
                      ]
                  },
                  {
                      prop5: someValue,
                      prop2: someValue
                  }
              ];
          
          
               function removeObjects(content, values) {
                   debugger;
                  if (!content || content.length === 0) {
                    return
                  }
                  content = content.filter((c) => {
                    if (!c.myProperty) return true
                     return c.myProperty.indexOf(values) > 0
                  })
                  // Here is my problem since I am supposed to do a recursive call on each of child contents,
                  // how do I merge back the original array?
                  return content.map(x => ({
                      ...x,
                      content: removeObjects(x.content, values)
                  }))
                }
          
                console.log(removeObjects(content, 'x'))

          【讨论】:

          • 我看到带有 myValue 和 otherValue 的两个对象都被删除了。
          • 如果对象没有 myProperty 键,则不应删除该对象。仅当存在 myProperty 键且值等于 myValue 时,才必须删除该对象。
          • 对不起,但您的问题要求删除所有包含 values 的键,在此示例中,myValueotherValue 都包含 x
          • 抱歉,如果我的问题不清楚。但是,如果您查看我的问题的需求部分,我曾提到 myProperty 应该与值 myValue 匹配。
          • 此外,您的问题是` // 如何合并回原始数组?` 部分,过滤逻辑 ` content.filter() => ...` 是你必须修改的东西
          猜你喜欢
          • 1970-01-01
          • 2021-10-29
          • 2021-01-30
          • 1970-01-01
          • 2021-12-28
          • 2020-12-07
          • 2017-12-18
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多