topological-sort-group
Version:
Topological sorting and cycle detection. Optional grouping for parallel processing
58 lines (57 loc) • 2.11 kB
JavaScript
import get from './deepGet.js';
const isArray = Array.isArray || ((x)=>Object.prototype.toString.call(x) === '[object Array]');
let Graph = class Graph {
static from(nodes, options) {
const graph = new Graph(options);
nodes.forEach((node)=>isArray(node) ? graph.add.apply(graph, node) : graph.add(node));
return graph;
}
key(keyOrValue) {
if (this.path) return typeof keyOrValue === 'object' ? get(keyOrValue, this.path) : keyOrValue;
return keyOrValue;
}
keys() {
const keys = [];
for(const key in this.nodeMap)keys.push(key);
return keys;
}
value(key) {
return this.nodeMap[key].value;
}
edges(key) {
return this.nodeMap[key].edges;
}
add(keyOrValue, toKeyOrValue) {
const key = this.key(keyOrValue);
const value = this.path ? typeof keyOrValue === 'object' ? keyOrValue : undefined : keyOrValue;
if (value !== undefined) {
if (this.nodeMap[key] === undefined) this.nodeMap[key] = {
value,
edges: []
};
else if (this.nodeMap[key].value !== value) throw new Error(`Adding different node values to same graph. Key ${key}. Existing: ${JSON.stringify(this.nodeMap[key].value)}. New: ${JSON.stringify(value)}`);
}
// biome-ignore lint/style/noArguments: <explanation>
if (arguments.length === 1) return;
// add edge
this.add(toKeyOrValue);
const toKey = this.key(toKeyOrValue);
this.nodeMap[key].edges.push(toKey);
}
degrees() {
const degrees = {};
for(const from in this.nodeMap){
if (degrees[from] === undefined) degrees[from] = 0;
this.nodeMap[from].edges.forEach((key)=>{
if (degrees[key] === undefined) degrees[key] = 0;
degrees[key]++;
});
}
return degrees;
}
constructor(options){
this.path = options ? options.path || undefined : undefined;
this.nodeMap = {};
}
};
export { Graph as default };