UNPKG

dag-iterator

Version:

utility tool to traverse DAG graphs in JavaScript

102 lines (101 loc) 3.83 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var TraversalMode; (function (TraversalMode) { TraversalMode[TraversalMode["DFS"] = 0] = "DFS"; TraversalMode[TraversalMode["BFS"] = 1] = "BFS"; })(TraversalMode = exports.TraversalMode || (exports.TraversalMode = {})); function iterateDfs(nodes, edges, func, untilNode) { var options = { traversalMode: TraversalMode.DFS, untilNode: untilNode, }; return _iterate(nodes, edges, func, options); } exports.iterateDfs = iterateDfs; function iterateBfs(nodes, edges, func, untilNode) { var options = { traversalMode: TraversalMode.BFS, untilNode: untilNode, }; return _iterate(nodes, edges, func, options); } exports.iterateBfs = iterateBfs; function iterate(nodes, edges, func, untilNode) { return iterateDfs(nodes, edges, func, untilNode); } exports.iterate = iterate; function _iterate(nodes, edges, func, options) { if (nodes.length === 0 || edges.length === 0) { return; } var nodeStorage = []; var nodeVisited = {}; var nodeMap = arrToObj(nodes, 'name'); var edgeSrcMap = tuplesToObj(edges.map(function (edge) { return [edge.src, edge.dst]; })); var edgeDstMap = tuplesToObj(edges.map(function (edge) { return [edge.dst, edge.src]; })); Array.prototype.push.apply(nodeStorage, getFirstNodes()); var i = 0; while (nodeStorage.length) { var node = getNextNode(nodeStorage, options.traversalMode); var parentNodes = getParentNodes(node); nodeVisited[node] = parentNodes.reduce(function (prev, curr) { return Math.max(prev, nodeVisited[curr] + 1); }, 0); var nodeData = getDataFromNode(node); var parentNodesData = parentNodes.map(getDataFromNode); func.call(null, nodeData, parentNodesData, i++, nodeVisited[node]); if (options.untilNode && node == options.untilNode) { break; } getChildNodes(node, true).forEach(function (childNode) { var unvisitedParents = getParentNodes(childNode, true); if (unvisitedParents.length === 0) { nodeStorage.push(childNode); } }); } function getFirstNodes() { return nodes.filter(function (node) { return edgeSrcMap.hasOwnProperty(node.name) && !edgeDstMap.hasOwnProperty(node.name); }) .map(function (node) { return node.name; }); } function getNextNode(arr, traversalMode) { return traversalMode === TraversalMode.DFS ? arr.pop() : arr.shift(); } function getParentNodes(nodeName, onlyUnvisited) { if (onlyUnvisited === void 0) { onlyUnvisited = false; } var parentNodes = edgeDstMap[nodeName] || []; return onlyUnvisited === false ? parentNodes : parentNodes.filter(filterNotVisited); } function getChildNodes(nodeName, onlyUnvisited) { if (onlyUnvisited === void 0) { onlyUnvisited = false; } var childNodes = edgeSrcMap[nodeName] || []; return onlyUnvisited === false ? childNodes : childNodes.filter(filterNotVisited); } function filterNotVisited(nodeName) { return !nodeVisited.hasOwnProperty(nodeName); } function getDataFromNode(nodeName) { return nodeMap[nodeName].data; } } function tuplesToObj(tuples) { return tuples.reduce(function (prev, curr) { var key = curr[0], val = curr[1]; prev[key] = prev.hasOwnProperty(key) ? [].concat(prev[key], val) : [val]; return prev; }, {}); } function arrToObj(arr, attr) { return arr.reduce(function (prev, curr) { var key = curr[attr], val = curr; prev[key] = prev.hasOwnProperty(key) ? [].concat(prev[key], val) : val; return prev; }, {}); }