一個(gè)遞歸案例

// 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);
?著作權(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ù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容