04.02.2021, 17:33
|
Аспирант
|
|
Регистрация: 27.11.2017
Сообщений: 45
|
|
Обмен узлов между двумя деревьями
Здравствуйте!!!
Хочу разобраться как можно осуществить смену узлов 2х деревьев с n вложенностью(узел получаем по клику, по факту это будет драг энд дроп). Корневой узел перетаскивает всех дочерних, любой дочерний может стать корневым и дочерним для любого другого узла в своем дереве или соседнем. Учитывается позиция.
1. Какие нужно учесть условия чтобы это стало возможо?
2. Задачка конечно ппц, хочется както понять с чего начать)
Допустим есть входящие данные такие:
const tree1 = [
{
id: 1,
title: 'node1',
children: [
{
id: 3,
title: 'sub node1' ,
},
{
id: 4,
title: 'sub node1' ,
children: [ { id: 5, title: 'sub sub node1'}]
}
] ,
},
{
id: 2,
title: 'node2',
children: [
{
id: 6,
title: 'sub node2' ,
},
{
id: 7, title: 'sub node2' ,
children: [ { id: 8, title: 'sub sub node2'}]
}
] ,
}
];
const tree2 = [
{
id: 9,
title: 'node1',
children: [
{
id: 10,
title: 'sub node1' ,
},
{
id: 11, title: 'sub node1' ,
children: []
}
] ,
},
{
id: 12,
title: 'node2',
children: [
{
id: 13,
title: 'sub node2' ,
},
{
id: 14,
title: 'sub node2' ,
children: [ { id: 15, title: 'sub sub node2'}]
}
] ,
}
];
const treeToTreeNodes = (tree1, tree2) => {
}
Последний раз редактировалось jabbascript, 04.02.2021 в 17:39.
|
|
04.02.2021, 18:16
|
|
Профессор
|
|
Регистрация: 03.02.2020
Сообщений: 2,745
|
|
По моему у ваших деревьев не хватает полноценного корня.
Должно быть как то так
const tree1 = {
id: 0,
title: 'root',
children: [
{
id: 1,
title: 'node1',
children: [
{
id: 3,
title: 'sub node1' ,
},
{
id: 4,
title: 'sub node1' ,
children: [ { id: 5, title: 'sub sub node1'}]
}
] ,
},
{
id: 2,
title: 'node2',
children: [
{
id: 6,
title: 'sub node2' ,
},
{
id: 7, title: 'sub node2' ,
children: [ { id: 8, title: 'sub sub node2'}]
}
] ,
}
]
};
const treeToTreeNodes = (tree1, tree2) => {}
И какая конкретно операция должна быть выполнена? Что вставить и куда?
|
|
05.02.2021, 08:54
|
Аспирант
|
|
Регистрация: 27.11.2017
Сообщений: 45
|
|
Допустим я беру и удаляю ноду из tree2:
{
id: 12,
title: 'node2',
children: [
{
id: 13,
title: 'sub node2' ,
},
{
id: 14,
title: 'sub node2' ,
children: [ { id: 15, title: 'sub sub node2'}]
}
] ,
}
и ее вставляю в tree1 между:
{
id: 6,
title: 'sub node2' ,
},
и
{
id: 7, title: 'sub node2' ,
children: [ { id: 8, title: 'sub sub node2'}]
}
и так далее все возможные комбинации.
|
|
05.02.2021, 11:05
|
|
Профессор
|
|
Регистрация: 03.02.2020
Сообщений: 2,745
|
|
Если такие операции требуются часто, я бы сделал класс, хотя бы с минимально необходимыми функциями работы с деревом.
Ну как то так
class Node {
// Создает узел дерева.
// fields - объект с полями определяемыми пользователем
// childs - массив дочерних узлов (необязат)
constructor (fields, childs) {
this.parent = null;
this.childs = [];
for (const f in fields) {
this[f] = fields[f];
}
if (childs) {
for (const ch of childs) {
this.append(ch);
}
}
}
// Добавить узел nd, как последний дочерний к текущему
append (nd) {
nd.remove();
nd.parent = this;
this.childs.push(nd)
return this
}
// Найти в текущем и среди всех его потомков узел, удовлетворяющий условию,
// задаваемому функцией fcmp
find (fcmp) {
if (fcmp(this)) return this;
for (const ch of this.childs) {
const rf = ch.find (fcmp)
if (rf) return rf;
}
return null;
}
// Удалить узел
// nd.remove () удаляет узел nd из его родителя.
// par.remove (nd) удаляет из дочерних par узел nd
remove (nd) {
let par = this;
if (nd === undefined) {
par = this.parent;
nd = this;
}
if (!par || !nd) return
const ind = par.childs.indexOf(nd);
if (ind < 0) return;
par.childs.splice(ind, 1);
nd.parent = null;
return nd;
}
// Вставляет узел nd перед текущим, в его родительский узел, если он есть
before (nd) {
const par = this.parent;
if (!par) return;
nd.remove();
const ind = par.childs.indexOf(nd);
par.childs.splice(ind, 0, nd)
nd.parent = this;
return this;
}
toString () {
let s = '{'
for (const f in this) {
if (f == 'childs') continue;
if (f == 'parent') continue;
s += `${f}: ${this[f].toString()}, `
}
s+='childs: ['
for (const ch of this.childs) {
s+=ch.toString() + ','
}
s+=']}'
return s
}
}
const tree1 = new Node ({},
[
new Node ({id: 1, title: 'node1'},
[
new Node ({id: 3, title: 'sub node1'}),
new Node ({id: 4, title: 'sub node1'}, [new Node ({ id: 5, title: 'sub sub node1'})]),
]),
new Node ({id: 2, title: 'node2'},
[
new Node ({id: 6, title: 'sub node2'}),
new Node ({id: 7, title: 'sub node2'}, [new Node ({ id: 8, title: 'sub sub node2'})]),
])
]);
const tree2 = new Node ({},
[
new Node ({id: 9, title: 'node1'},
[
new Node ({id: 10, title: 'sub node1'}),
new Node ({id: 11, title: 'sub node1'}),
]),
new Node ({id: 12, title: 'node2'},
[
new Node ({id: 13, title: 'sub node2'}),
new Node ({id: 14, title: 'sub node2'}, [new Node ({ id: 15, title: 'sub sub node2'})]),
])
]);
console.log(tree1.toString());
console.log(tree2.toString());
// Допустим я беру и удаляю ноду из tree2:
// и ее вставляю в tree1 между:
const nd12 = tree2.find (nd => nd.id == 12)
const nd7 = tree1.find (nd => nd.id == 7)
nd7.before(nd12)
console.log(tree1.toString());
console.log(tree2.toString());
|
|
05.02.2021, 14:30
|
|
Профессор
|
|
Регистрация: 03.02.2020
Сообщений: 2,745
|
|
Сообщение от Vlasenko Fedor
|
тут вопрос целесообразности своего велосипеда или изспользованя готовых либ
|
Эти готовые либы работают с DOM.
А оно надо?
Зачем в простом случае тащить готовую либу, где 90% не требуется?
Сообщение от Vlasenko Fedor
|
https://learn.javascript.ru/drag-and-drop-plus
|
Где дерево то?
|
|
05.02.2021, 18:13
|
|
Профессор
|
|
Регистрация: 13.03.2013
Сообщений: 1,572
|
|
Сообщение от voraa
|
Зачем в простом случае тащить готовую либу, где 90% не требуется?
|
чтоб не тратить время на свой велосипед, взять готовое,чтоб не тестить и не ловить баги во всех браузерах, потратить время на другое
в нынешнее время плевать на 10k на вебе можно
в конце ТС ответил про react
avesome react tree
https://reactscript.com/best-tree-view/
с React не подскажу, у меня к нему особое мнение
|
|
|
|