Этот тип проблемы идеально подходит для изучения взаимной рекурсии.
Сначала мы сделаем способ traverse
одного node
и его children
, используя функцию более высокого порядка f
-
const traverse = (f, { children = [], ...node }) =>
f ({ ...node, children: children.map (c => traverse (f, c)) })
Например, добавить свойство hello
, установленное на 'world'
для каждого узла -
traverse
( node => ({ ...node, hello: 'world' })
, { a: 1, children: [ { b: 2 } ] }
)
// { a: 1
// , children:
// [ { b: 2
// , children: []
// , hello: 'world'
// }
// ]
// }
Но это работает только для одного узла,У вас есть массив узлов, поэтому -
const traverseAll = (f, nodes = []) =>
nodes.map (node => traverse (f, node))
Когда вы оглядываетесь назад на traverse
, мы видим, что повторились ( полужирным ) -
const traverse = (f, { children = [], ...node }) =>
f ({ ...node, children: <b>children.map (c => traverse (f, c))</b> })
const traverseAll = (f, nodes = []) =>
<b>nodes.map (node => traverse (f, node))</b>
Используя взаимно рекурсивное определение, мы пишем гармоничную пару -
const traverseAll = (f, nodes = []) =>
nodes.map (node => <b>traverse (f, node)</b>)
const traverse = (f, { children = [], ...node }) =>
f ({ ...node, children: <b>traverseAll (f, children)</b> })
Проверьте всю программу в вашем браузере ниже -
const traverseAll = (f, nodes = []) =>
nodes.map (node => traverse (f, node))
const traverse = (f, { children = [], ...node }) =>
f ({ ...node, children: traverseAll (f, children) })
const nodes =
[ { id: 1
, children:
[ { id: 2
, children: []
}
, { id: 3
, children:
[ { id: 4
, children: []
}
]
}
]
}
, { id: 5
, children: []
}
]
console.log
( traverseAll
( node => ({ ...node, open: 'fa fa-open' })
, nodes
)
)
// [ { id: 1
// , children:
// [ { id: 2, children: [], open: 'fa fa-open' },
// { id: 3
// , children:
// [ { id: 4
// , children: []
// , open: 'fa fa-open'
// }
// ]
// , open: 'fa fa-open'
// }
// ]
// , open: 'fa fa-open'
// }
// , { id: 5
// , children: []
// , open: 'fa fa-open'
// }
// ]