Показать сообщение отдельно
  #4 (permalink)  
Старый 05.02.2021, 11:05
Аватар для voraa
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 2,701

Если такие операции требуются часто, я бы сделал класс, хотя бы с минимально необходимыми функциями работы с деревом.
Ну как то так
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());
Ответить с цитированием