简体   繁体   中英

Remove objects from a deeply nested object array by property value

Consider I have a nested object array. One possible example scenario could be:

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

Here are the possibilities:

  • The structure starts with content[] but the descendants may or may not have content property.
  • The level of the hierarchy can be of any number.
  • The properties contained by the objects are not always the same ie one object may have x, y, z properties while the other may have v, w, z properties.
  • If any object in the hierarchy has myProperty key, there won't be content key.
  • More than one object in the hierarchy can have myProperty with value 'myValue .

My requirement:

  • If at any level an object has the property myProperty with the value myValue then remove the entire object (NOT JUST THE PROPERTY) from the hierarchy.

My attempt so far:

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

The following recursively returns a new array without mutating the original

 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))

Expected output:

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

Try this, (this is JavaScript version)

 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'))

You can use below function to get expected result:

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

Use recursive approach, to have filter array of items and their content array.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM