// JSON 數(shù)據(jù)
const data ={
"nodes": [
{
"id": "aee0e753-3643-452a-9fb5-9d2dda953244",
"type": "semantic_segmentation",
"title": "語義分割",
"subtitle": "語義分割",
"position": {
"x": 49840,
"y": 49810
},
"level": 0,
"branch": 0,
"properties": {
"attrs": {
"model_id": {
"type": "string",
"description": "模型ID",
"required": true,
"name": "模型ID"
}
},
"input_params": {
"image": {
"type": "image",
"description": "圖片",
"required": true,
"name": "圖片"
}
},
"output_params": {
"predictions": {
"type": "object",
"description": "分割結(jié)果",
"required": true,
"name": "預(yù)測(cè)結(jié)果"
}
}
},
"iconType": "semantic_segmentation"
},
{
"id": "50865899-f9dd-4417-973d-2ccce4c994ef",
"type": "image_clip",
"title": "圖片裁剪",
"subtitle": "圖片裁剪",
"position": {
"x": 49840,
"y": 49960
},
"level": 1,
"branch": 0,
"properties": {
"attrs": {
"x": {
"type": "number",
"description": "x坐標(biāo)",
"required": true,
"name": "x坐標(biāo)"
},
"y": {
"type": "number",
"description": "y坐標(biāo)",
"required": true,
"name": "y坐標(biāo)"
},
"width": {
"type": "number",
"description": "寬度",
"required": true,
"name": "寬度"
},
"height": {
"type": "number",
"description": "高度",
"required": true,
"name": "高度"
}
},
"input_params": {
"image": {
"type": "image",
"description": "圖片",
"required": true,
"name": "圖片"
}
},
"output_params": {
"image": {
"type": "image",
"description": "裁剪后的圖片",
"required": true,
"name": "裁剪后的圖片"
}
}
},
"iconType": "image_clip"
},
{
"id": "8ca5e332-3889-40bc-9991-c68ded5af390",
"type": "visualize",
"title": "推理結(jié)果可視化",
"subtitle": "推理結(jié)果可視化",
"position": {
"x": 49840,
"y": 50560
},
"level": 5,
"branch": 0,
"properties": {
"attrs": {
"color": {
"type": "string",
"description": "顏色",
"required": true,
"default": "#00FF00",
"name": "顏色"
},
"line_width": {
"type": "number",
"description": "線寬",
"required": true,
"default": 2,
"name": "線寬"
}
},
"input_params": {
"predictions": {
"type": "object",
"description": "推理結(jié)果",
"required": true,
"name": "推理結(jié)果"
},
"image": {
"type": "image",
"description": "圖片",
"required": true,
"name": "圖片"
}
},
"output_params": {
"image": {
"type": "image",
"description": "可視化結(jié)果",
"required": true,
"name": "可視化結(jié)果"
}
}
},
"iconType": "visualize"
},
{
"id": "32fda8fa-cdea-48aa-bb4e-ee578a0f5bd5",
"type": "image_clip",
"title": "圖片裁剪_1",
"subtitle": "圖片裁剪",
"position": {
"x": 49840,
"y": 50110
},
"level": 2,
"branch": 0,
"properties": {
"attrs": {
"x": {
"type": "number",
"description": "x坐標(biāo)",
"required": true,
"name": "x坐標(biāo)"
},
"y": {
"type": "number",
"description": "y坐標(biāo)",
"required": true,
"name": "y坐標(biāo)"
},
"width": {
"type": "number",
"description": "寬度",
"required": true,
"name": "寬度"
},
"height": {
"type": "number",
"description": "高度",
"required": true,
"name": "高度"
}
},
"input_params": {
"image": {
"type": "image",
"description": "圖片",
"required": true,
"name": "圖片"
}
},
"output_params": {
"image": {
"type": "image",
"description": "裁剪后的圖片",
"required": true,
"name": "裁剪后的圖片"
}
}
},
"iconType": "image_clip"
},
{
"id": "f65b6774-ebeb-4d62-bb52-ca0f2aa69636",
"type": "visualize",
"title": "推理結(jié)果可視化_1",
"subtitle": "推理結(jié)果可視化",
"position": {
"x": 49840,
"y": 50260
},
"level": 3,
"branch": 0,
"properties": {
"attrs": {
"color": {
"type": "string",
"description": "顏色",
"required": true,
"default": "#00FF00",
"name": "顏色"
},
"line_width": {
"type": "number",
"description": "線寬",
"required": true,
"default": 2,
"name": "線寬"
}
},
"input_params": {
"predictions": {
"type": "object",
"description": "推理結(jié)果",
"required": true,
"name": "推理結(jié)果"
},
"image": {
"type": "image",
"description": "圖片",
"required": true,
"name": "圖片"
}
},
"output_params": {
"image": {
"type": "image",
"description": "可視化結(jié)果",
"required": true,
"name": "可視化結(jié)果"
}
}
},
"iconType": "visualize"
},
{
"id": "52644f3c-6057-4450-8a1a-6737b477d365",
"type": "semantic_segmentation",
"title": "語義分割_1",
"subtitle": "語義分割",
"position": {
"x": 49840,
"y": 50410
},
"level": 4,
"branch": 0,
"properties": {
"attrs": {
"model_id": {
"type": "string",
"description": "模型ID",
"required": true,
"name": "模型ID"
}
},
"input_params": {
"image": {
"type": "image",
"description": "圖片",
"required": true,
"name": "圖片"
}
},
"output_params": {
"predictions": {
"type": "object",
"description": "分割結(jié)果",
"required": true,
"name": "預(yù)測(cè)結(jié)果"
}
}
},
"iconType": "semantic_segmentation"
}
],
"connections": [
{
"id": "input-conn",
"from": "input",
"to": "aee0e753-3643-452a-9fb5-9d2dda953244"
},
{
"id": "19b53f7e-6093-4fb5-ba85-93a792b65cfc",
"from": "aee0e753-3643-452a-9fb5-9d2dda953244",
"to": "50865899-f9dd-4417-973d-2ccce4c994ef"
},
{
"id": "6484a860-c0ed-4958-b0ac-9e8d1fc91072",
"from": "8ca5e332-3889-40bc-9991-c68ded5af390",
"to": "output"
},
{
"id": "be0df973-193f-460b-9b7d-1bcecb49f68c",
"from": "50865899-f9dd-4417-973d-2ccce4c994ef",
"to": "32fda8fa-cdea-48aa-bb4e-ee578a0f5bd5"
},
{
"id": "f7e1e6a2-fbc4-4776-bf8f-7b55020e16be",
"from": "32fda8fa-cdea-48aa-bb4e-ee578a0f5bd5",
"to": "f65b6774-ebeb-4d62-bb52-ca0f2aa69636"
},
{
"id": "4732cd83-702b-4973-8ef0-1aa90d2c3113",
"from": "f65b6774-ebeb-4d62-bb52-ca0f2aa69636",
"to": "52644f3c-6057-4450-8a1a-6737b477d365"
},
{
"id": "8cf75af7-9114-454b-9cac-c8a4a2637420",
"from": "52644f3c-6057-4450-8a1a-6737b477d365",
"to": "8ca5e332-3889-40bc-9991-c68ded5af390"
}
]
}
// 原始數(shù)據(jù)
// 將 nodes 轉(zhuǎn)換為以 id 為鍵的 Map,便于快速查找
const nodesMap = new Map(data.nodes.map(node => [node.id, node]));
/**
* 遞歸查找指定節(jié)點(diǎn)的上游節(jié)點(diǎn)(滿足 output_params 包含目標(biāo)屬性)
* @param {string} currentNodeId 當(dāng)前節(jié)點(diǎn) ID(初始為目標(biāo)節(jié)點(diǎn) ID)
* @param {string} targetParam 需要檢查的 output_params 屬性名(如 'image' 或 'predictions')
* @param {Set} visited 已訪問的節(jié)點(diǎn) ID 集合(防止循環(huán))
* @param {Array} result 結(jié)果數(shù)組(存儲(chǔ)符合條件的上游節(jié)點(diǎn))
* @returns {Array} 所有符合條件的上游節(jié)點(diǎn)
*/
function findUpstreamNodesByOutputParam(
currentNodeId,
targetParam,
visited = new Set(),
result = []
) {
// 1. 找到當(dāng)前節(jié)點(diǎn)的所有上游連接(即 connections 中 to === currentNodeId 的記錄)
const incomingConnections = data.connections.filter(conn => conn.to === currentNodeId);
// 2. 遍歷所有上游連接,處理每個(gè)上游節(jié)點(diǎn)
for (const conn of incomingConnections) {
const fromNodeId = conn.from; // 上游節(jié)點(diǎn) ID
// 3. 跳過輸入源(from 為 "input" 的情況)
if (fromNodeId === 'input') continue;
// 4. 檢查上游節(jié)點(diǎn)是否存在(避免無效節(jié)點(diǎn))
if (!nodesMap.has(fromNodeId)) continue;
const fromNode = nodesMap.get(fromNodeId); // 獲取上游節(jié)點(diǎn)對(duì)象
// 5. 避免重復(fù)處理(循環(huán)引用防護(hù))
if (visited.has(fromNodeId)) continue;
visited.add(fromNodeId); // 標(biāo)記為已訪問
// 6. 檢查上游節(jié)點(diǎn)的 output_params 是否包含目標(biāo)屬性
if (fromNode.properties?.output_params?.[targetParam]) {
result.push(fromNode); // 符合條件則加入結(jié)果
}
// 7. 遞歸查找該上游節(jié)點(diǎn)的上游節(jié)點(diǎn)(繼續(xù)向上遍歷)
findUpstreamNodesByOutputParam(fromNodeId, targetParam, visited, result);
}
return result;
}
// --------------------------
// 使用示例:查找兩種類型的節(jié)點(diǎn)
// --------------------------
// 目標(biāo)節(jié)點(diǎn) ID(示例中的可視化節(jié)點(diǎn))
const targetNodeId = '8ca5e332-3889-40bc-9991-c68ded5af390';
// 查找 output_params 包含 "predictions" 的上游節(jié)點(diǎn)(如語義分割、語義分割_1)
const predictionsUpstreamNodes = findUpstreamNodesByOutputParam(
targetNodeId,
'predictions'
);
// 查找 output_params 包含 "image" 的上游節(jié)點(diǎn)(如圖片裁剪、圖片裁剪_1、推理結(jié)果可視化_1)
const imageUpstreamNodes = findUpstreamNodesByOutputParam(
targetNodeId,
'image'
);
console.log('找到 predictions 上游節(jié)點(diǎn):', predictionsUpstreamNodes);
console.log('找到 image 上游節(jié)點(diǎn):', imageUpstreamNodes);
一個(gè)遞歸案例
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
相關(guān)閱讀更多精彩內(nèi)容
- 遞歸的作用 遞歸總是走到出口的時(shí)候,再向上一步一步的賦值計(jì)算后返回結(jié)果 做遞歸的兩個(gè)重要條件(因素) 1.計(jì)...
- 文科生快速入門python(十二) | 經(jīng)典的函數(shù)遞歸案例 今天,數(shù)據(jù)猿重點(diǎn)整理了python的遞歸函數(shù)相關(guān)內(nèi)容,...
- 源代碼: 這段代碼定義了一個(gè) TypeScript 的類型工具 RecursivePartial<T>,其主要功能...
- 今天我們繼續(xù)使用 Vue 的擼我們的實(shí)戰(zhàn)項(xiàng)目,只有在實(shí)戰(zhàn)中我們才會(huì)領(lǐng)悟更多,光紙上談兵然并卵,繼上篇我們的 《Vu...