#javascript #algorithm #treeview
Вопрос:
Допустим, у меня есть объект Javascript, структурированный ниже :
const data = [{ id: 1, type: "ORGANIZATION", children: [ { id: 11, type: 'ORGANIZATION', children: [ { id: 111, type: 'DEPARTMENT', children: [ { id: 1111, type: 'DEPARTMENT', children: null // final child } ] }, { id: 112, type: 'DEPARTMENT', children: [ //more children ] } ] }, { id: 12, type: 'DEPARTMENT', children: [ //more children ] } ] }]
В приведенной выше структуре ORGANIZATION
узел может иметь список меньших ORGANIZATION
узлов и DEPARTMENT
узлов, в то время DEPARTMENT
как узел может иметь список меньших DEPARTMENT
. Я пытаюсь написать алгоритм, чтобы получить родительский узел любого узла и информацию о нем в дереве, следуя этим правилам:
- Алгоритм вернет 2 объекта
orgInfo
иdeptInfo
. - Если узел является
ORGANIZATION
типом, вернитесьorgInfo
с самой информацией и вернитеdeptInfo
значение null. - Если узел является
DEPARTMENT
типом, верните шкафorgInfo
и вернитесьdeptInfo
с самой информацией.
Например , если алгоритм ищет id:1111
узел, он вернет deptInfo
тот, у которого id = 1111, а orgInfo
у которого id = 11 (родительский шкаф)
У меня уже есть свой алгоритм на Javascript, но когда я пытаюсь поместить его в свое приложение React Native, он отображается медленно. Вот мой код:
const itemSelector = createSelector( // using selector for Redux [ state =gt; state.LookUpReducer.selectedItem, state =gt; state.globalReducer.department_tree, ], (item, tree) =gt; { let nodePath = []; let orgId, deptId; searchTree(tree, item.id, (item) =gt; nodePath = [...item]); console.log(nodePath); nodePath.reverse().some(item =gt; {//reverse the path to find the closet parent if (item.type == 'ORGANIZATION') { orgId = item.id return true } return false }) nodePath.some(item =gt; { if (item.type == 'DEPARTMENT') { deptId = item.id return true } return false }) console.log("OrgID: " orgId " DeptID:" deptId); return { ..... } } ) const searchTree = (tree, nodeId, callback, path = []) =gt; { //nodeId : the node to be search tree.forEach(item =gt; { path.push({ id: item.id, type: item.type }); if (item.id == nodeId) { callback(path); // node founded } else { if (item.children) searchTree(item.children, nodeId, callback, path) } path.pop(); }) }
Я знаю, что мой алгоритм проходит через все узлы в дереве, и я все еще не знаю, как остановить его, когда он найдет узел. Кто-нибудь может помочь мне найти лучшее решение для моего алгоритма ?
Ответ №1:
Вы можете просто выполнить поиск по глубине, и когда цикл возвращается из внутренних циклов, если найден отдел, но не организация, вы можете просто указать первую организацию, которую он пересекает, поскольку она уже выполняется в обратном порядке.
const data = [{ id: 1, type: "ORGANIZATION", children: [ { id: 11, type: 'ORGANIZATION', children: [ { id: 111, type: 'DEPARTMENT', children: [ { id: 1111, type: 'DEPARTMENT', children: null // final child } ] }, { id: 112, type: 'DEPARTMENT', children: [ //more children ] } ] }, { id: 12, type: 'DEPARTMENT', children: [ //more children ] } ] }] let org, dep; let loop = (nodes, id) =gt; { if (org) { return; // when you have already fond the org } if(!nodes){ return; // incase the final child } nodes.forEach(node =gt; { if (node.id === id) { node.type === 'ORGANIZATION' ? org = node : dep = node; // if you find the org or dep no need to loop children } else { loop(node.children, id); // if not found go one level deeper. if (!org amp;amp; dep amp;amp; node.type === 'ORGANIZATION') { // on returning from deeper level when you have found department but not an organization yet set it here org = node; } } }); } loop(data, 111); console.log('organization :',org); console.log('department :', dep);