graphinius
Version:
Generic graph library in Typescript
174 lines (154 loc) • 3.63 kB
text/typescript
import {BaseGraph} from '../core/base/BaseGraph'
import {BaseNode} from '../core/base/BaseNode';
import {BaseEdge} from '../core/base/BaseEdge';
/**
* Method to deep clone an object
*
* @param obj
* @returns {*}
*
*/
function clone(obj: any): any {
if (obj === null || typeof obj !== 'object') {
return obj;
}
/**
* @description for the sake of cloning graph structures, we have specialized
* clone methods within the BaseGraph, BaseNode & BaseEdge classes
*/
if (obj instanceof BaseGraph || obj instanceof BaseNode || obj instanceof BaseEdge) {
return null;
}
let cloneObj = Array.isArray(obj) ? [] : {};
for (let attribute in obj) {
if ( !obj.hasOwnProperty(attribute) ) {
continue;
}
if (typeof obj[attribute] === "object") {
cloneObj[attribute] = clone(obj[attribute]);
} else {
cloneObj[attribute] = obj[attribute];
}
}
return cloneObj;
}
/**
*
* @param arr
*
* @todo it's obvious, nevertheless needs some testing...
*/
function shuffleArray(arr: Array<any>): Array<any> {
for (let i = arr.length - 1; i >= 0; i--) {
let randomIndex = Math.floor(Math.random() * (i + 1));
let itemAtIndex = arr[randomIndex];
arr[randomIndex] = arr[i];
arr[i] = itemAtIndex;
}
return arr;
}
/**
* @args an Array of any kind of objects
* @cb callback to return a unique identifier;
* if this is duplicate, the object will not be stored in result.
* @returns {Array}
*
* @todo
*/
function mergeArrays(args: Array<Array<any>>, cb: Function = undefined) {
for (let arg_idx in args) {
if (!Array.isArray(args[arg_idx])) {
throw new Error('Will only mergeArrays arrays');
}
}
let seen = {},
result = [],
identity;
for (let i = 0; i < args.length; i++) {
for (let j = 0; j < args[i].length; j++) {
identity = typeof cb !== 'undefined' ? cb(args[i][j]) : args[i][j];
if (seen[identity] !== true) {
result.push(args[i][j]);
seen[identity] = true;
}
}
}
return result;
}
/**
* Overwrites obj1's values with obj2's and adds obj2's if non existent in obj1
* @param args Array of all the object to take keys from
* @returns result object
*/
function mergeObjects(args: Array<Object>) {
for (let i = 0; i < args.length; i++) {
if (Object.prototype.toString.call(args[i]) !== '[object Object]') {
throw new Error('Will only take objects as inputs');
}
}
let result = {};
for (let i = 0; i < args.length; i++) {
for (let key in args[i]) {
if (args[i].hasOwnProperty(key)) {
result[key] = args[i][key];
}
}
}
return result;
}
/**
* Takes two ordered number arrays and merges them. The returned array is
* also ordered and does not contain any duplicates.
*
* @param a: first array
* @param b: second array
*/
function mergeOrderedArraysNoDups(a: Array<number>, b: Array<number>): Array<number> {
let ret: Array<number> = [];
let idx_a = 0;
let idx_b = 0;
if (a[0] != null && b[0] != null) {
while (true) {
if (idx_a >= a.length || idx_b >= b.length) {
break;
}
if (a[idx_a] == b[idx_b]) {
if (ret[ret.length - 1] != a[idx_a]) {
ret.push(a[idx_a]);
}
idx_a++;
idx_b++;
continue;
}
if (a[idx_a] < b[idx_b]) {
ret.push(a[idx_a]);
idx_a++;
continue;
}
if (b[idx_b] < a[idx_a]) {
ret.push(b[idx_b]);
idx_b++;
}
}
}
while (idx_a < a.length) {
if (a[idx_a] != null) {
ret.push(a[idx_a]);
}
idx_a++;
}
while (idx_b < b.length) {
if (b[idx_b] != null) {
ret.push(b[idx_b]);
}
idx_b++;
}
return ret;
}
export {
clone,
shuffleArray,
mergeArrays,
mergeObjects,
mergeOrderedArraysNoDups
};