Change object property in nested array

I have an array:

   const array = [       { id: 1, parent_id: 0, visible: true },       { id: 2, parent_id: 0, visible: true },       { id: 3, parent_id: 1, visible: true },       { id: 4, parent_id: 3, visible: true },       { id: 5, parent_id: 4, visible: true },       { id: 6, parent_id: 4, visible: true },       { id: 7, parent_id: 3, visible: true },       { id: 8, parent_id: 2, visible: true }     ] 

I want to create a function with arguments ID and ARRAY, that return new array with VISIBLE = FALSE for this ID and every nested child by PARENT_ID.

My effort is like this

const result = []  const findFitstHandler = (id, arr) => {   let j   for (let i in arr) {     if (arr[i].id === id) {       result.push(arr[i].id)       j = arr[i].id     }   }   findNested(j, arr)    return array.map(item => {     if (result.includes(item.id)) {       return {         ...item,         visible: false       }     } else {       return item     }   }) }  const findNested = (id, arr) => {   for (let i in arr) {     if (arr[i].parent_id === id) {       result.push(arr[i].id)       findNested(arr[i].id, arr)     }   } } 

I’m sure there is a more elegant solution. Please, help me

Add Comment
2 Answer(s)

Try with array map method:

const array = [       { id: 1, parent_id: 0, visible: true },       { id: 2, parent_id: 0, visible: true },       { id: 3, parent_id: 1, visible: true },       { id: 4, parent_id: 3, visible: true },       { id: 5, parent_id: 4, visible: true },       { id: 6, parent_id: 4, visible: true },       { id: 7, parent_id: 3, visible: true },       { id: 8, parent_id: 2, visible: true }     ];      const getNewArray = (id, items) => items.map(item => {    if ([item.id, item.parent_id].includes(id)) {       item.visible = false;    }        return item; });      console.log(getNewArray(4, array));

Add Comment

I would break apart the recursive code that finds the list of descendants from the code that does the data manipulation. Here’s one possibility:

const descendants = (array, root) =>    [     root,      ...array .filter (({parent_id}) => parent_id == root)               .flatMap (({id}) => descendants (array, id))   ]  const changeBranch = (fn) => (array, root, keys = descendants (array, root)) =>   array .map (element => keys .includes (element .id) ? fn (element) : element)  const makeInvisible = changeBranch (   ({visible, ...rest}) => ({...rest, visible: false}) )  const array = [{ id: 1, parent_id: 0, visible: true }, { id: 2, parent_id: 0, visible: true }, { id: 3, parent_id: 1, visible: true }, { id: 4, parent_id: 3, visible: true }, { id: 5, parent_id: 4, visible: true }, { id: 6, parent_id: 4, visible: true }, { id: 7, parent_id: 3, visible: true }, { id: 8, parent_id: 2, visible: true }];      console .log (makeInvisible (array, 4))  console .log (makeInvisible (array, 2))
.as-console-wrapper {min-height: 100% !important; top: 0}

descendants finds the ids of the root id supplied and all the nodes descendant from it inside your array.

changeBranch takes a function to transform a node and returns a function that takes an array and the root id and returns a new array containing either the result of applying that function (when the node is descendant from the root) or the original value (when it isn’t.)

makeInvisible is the result of applying to changeBranch a function which sets visible to false. This is the final function you’re looking for.

Note that if your list is cyclic and not hierarchical, this will not work. Your stack would likely overflow.

Answered on July 16, 2020.
Add Comment

Your Answer

By posting your answer, you agree to the privacy policy and terms of service.