0

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 i.e. 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)
  }

4 Answers 4

2

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"
      }
    ]
Sign up to request clarification or add additional context in comments.

Comments

1

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

Comments

0

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

7 Comments

I see both objects with myValue and otherValue were removed.
If the object doesn't have myProperty key than it shouldn't remove the object. The object must be removed only if the myProperty key is present and the value is equal to myValue.
sorry, but your question asked that all keys that contain values to be removed, in this example both myValue and otherValue contain x
Apologies if my question wasn't clear. But if you look at the requirement part of my question, I had mentioned that myProperty should match the value myValue.
and beside, your problem was ` // how do I merge back the original array?` part, filtering logic ` content.filter() => ...` is something you have to tinker with
|
0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.