Структури даних - Rete.js

Структури даних

Подібно до графа, цей фреймворк містить дані у вигляді вузлів і ребер. Одне зауваження: у термінології редактора, ребра графа відомі як з’єднання.

Екземпляр NodeEditor зберігає ці дані в нормалізованому форматі, зокрема у вигляді двох окремих списків, що містять об’єкти такого типу:

  • { id: <string> } для вузлів
  • { id: <string>, source: <string>, target: <string> } для з’єднань
NodeEditor

Ініціалізація редактора передбачає використання базової схеми без будь-яких додаткових полів для початку:

ts
import { NodeEditor, BaseSchemes, getUID } from 'rete'

const editor = new NodeEditor<BaseSchemes>()

Додавання вузлів та з’єднан

Маючи справу з даними графа, у вас є можливість створювати довільні ідентифікатори для вузлів і з’єднань або використовувати існуючі.

ts
const a = { id: getUID() }
const b = { id: getUID() }
const connection = { id: getUID(), source: a.id, target: b.id }

await editor.addNode(a)
await editor.addNode(b)
await editor.addConnection(connection)

Отримання вузлів та з’єднань

Тепер ми можемо отримати список щойно доданих вузлів і з’єднань

ts
editor.getNodes() // returns [a, b]
editor.getConnections() // returns [connection]

У вас є всі необхідні методи для обробки графу, такі як отримання списку вхідних з’єднань або всіх вхідних вузлів, які ми обговоримо в наступних розділах.

Вхідні/вихідні з'єднання

Вхідні/вихідні з'єднання

Наступний код показує, як отримати список вхідних і вихідних з’єднань для node:

ts
const connections = editor.getConnections()

const incomingConnections = connections.filter(connection => connection.target === node.id)
const outgoingConnections = connections.filter(connection => connection.source === node.id)

Вхідні/вихідні вузли

Вхідні/вихідні вузли

Ми можемо використовувати змінні з попереднього розділу для отримання вхідних або вихідних вузлів:

ts
const incomers = incomingConnections.map(connection => editor.getNode(connection.source))
const outgoers = outgoingConnections.map(connection => editor.getNode(connection.target))

Взагалі-то цього достатньо для простих випадків, але якщо між вузлами існує більше одного з’єднання, нам доведеться видалити дублікати:

ts
Array.from(new Set(incomers))
Array.from(new Set(outgoers))

Просунуті методи

Зазначені вище підходи досить гнучкі, але вимагають самостійної імплементації більш складних методів. На щастя, пакет rete-structures пропонує такі методи, розділені на 4 категорії:

  • Маппінг: ітерація списку вузлів під час його перетворення або фільтрації
  • Множини: техніки роботи з графами як множинами, включаючи об’єднання, різницю та перетин.
  • Підграф: графи, які мають зв’язки «батько-дитина» між вузлами.
  • Траверс: обхід вузлів за їхніми з’єднаннями, наприклад отримання лише вхідних вузлів або всіх попередників.
rete-structures

Використання

Встановимо залежність

bash
npm i rete-structures

Використовуйте наступний оператор імпорту та декларацію

ts
import { structures } from 'rete-structures'

const graph = structures(editor)

graph.nodes()
graph.connections()

Існують інші методи graph, які служать різним цілям, продемонстровані нижче з кодом та інтерактивним превью. Отримані вузли помітні, а попередній перегляд дозволяє користувачам вибирати вузли та спостерігати за змінами.

Виконання будь-якого з методів зазвичай дає вузли, які не були відкинуті, а також їхні з’єднання, якщо обидва їхні вузли присутні.

Траверс

Коріння

Вузли без вхідних з'єднань відомі як кореневі вузли

ts
structures(graph).roots()
Preview needs JS to be enabled

Листя

Листові вузли – це вузли, які не мають вихідних з’єднань

ts
structures(graph).leaves()
Preview needs JS to be enabled

Вхідні

Вхідні вузли безпосередньо підключені до вибраного вузла

ts
structures(graph).incomers(selectedNodeId)
Preview needs JS to be enabled

Визідні

Вихідні вузли безпосередньо підключені до вибраного вузла

ts
structures(graph).outgoers(selectedNodeId)
Preview needs JS to be enabled

Попередники

Кожен вхідний вузол, а також його вхідні вузли тощо

ts
structures(graph).predecessors(selectedNodeId)
Preview needs JS to be enabled

Наступники

Кожен вихідний вузол, а також його вихідні вузли тощо

ts
structures(graph).successors(selectedNodeId)
Preview needs JS to be enabled

Маппінг

Фільтр

Фільтрування можна застосовувати як до вузлів, так і до з’єднань

ts
structures(graph).filter(Boolean, ({ source, target }) => source === selectedNodeId || target === selectedNodeId)
Preview needs JS to be enabled

Множини

У наступних прикладах показано випадки, коли вибраний вузол служить другим графом

Союз

Об'єднання графа і вузла з цього графа дає той самий граф

ts
structures(editor).union({ nodes: [selectedNode], connections: [] })
Preview needs JS to be enabled

Різниця

Віднімаючи вузол із графа, ви можете отримати новий графік без цього вузла

ts
structures(editor).difference({ nodes: [selectedNode], connections: [] })
Preview needs JS to be enabled

Перетин

Перетинаючи граф із вузлом із цього графу, ви отримаєте новий граф, який включає лише вибраний вузол

ts
structures(editor).intersection({ nodes: [selectedNode], connections: [] })
Preview needs JS to be enabled

Підграф

Ця категорія відноситься до графів, які містять вузли зі зв’язком «батько-дитина», зокрема вузли, у яких визначено поле parent та вкладені в інші вузли.

Діти

Список прямих нащадків, а саме дітей

ts
structures(editor).children((n) => n.id === selectedNodeId);
Preview needs JS to be enabled

Батько

Список батьків

ts
structures(editor).parents((n) => n.id === selectedNodeId);
Preview needs JS to be enabled

Нащадки

Список усіх нащадків, включаючи дітей, онуків і наступні покоління

ts
structures(editor).descendants((n) => n.id === selectedNodeId);
Preview needs JS to be enabled

Предки

Список усіх предків, від батьків до прадідів і далі

ts
structures(editor).ancestors((n) => n.id === selectedNodeId);
Preview needs JS to be enabled

Сироти

Вузли без указаної властивості parent

ts
structures(editor).orphans();
Preview needs JS to be enabled

Брати і сестри

Вузли, які мають спільного батька з вибраним вузлом, навіть якщо він не має батьків

ts
structures(editor).siblings((n) => n.id === selectedNodeId)
Preview needs JS to be enabled