DS-Plus

Implement non-native data structures in JavaScript with style.


Sometimes, the built-in data structures in JavaScript simply aren't adequate for the application being developed.

Fear not. DS-Plus gives developers fast and reliable data structures.

To use DS-Plus in one's project, all one needs to do is download its package with the following command:npm i ds-plus

Queue

Queues are very easy to implement with Plus. There are two initialization options for the data storage in the queue: an array, or a linked list.

Methods

constructor(data = null)

Initialize a new Queue object. Possible parameter(s) are: 'linkedlist'.

let Queue = new Plus.Queue();
let Queue = new Plus.Queue('linkedlist');

The returned Queue object has the following structure:

{
  data: [] || 'Linked List',
  ll: true || false
}

. . . . .

enqueue(...arguments)

Appends element(s) to the end of the data property. To pass several elements at once, simply separate each element by a comma.

Queue.enqueue(1);
Queue.enqueue(2, 3, 4);
Queue.enqueue('string', true, [1, 2, 3], { one: 'more' });

. . . . .

dequeue()

Removes and returns the first element from the data property. Returns null if the store is empty.

Queue.enqueue(1);
Queue.dequeue();  // 1
Queue.dequeue();  // null

. . . . .

front()

Returns the first element or node from the data property. Returns undefined or null if there are no elements.

Queue.enqueue(1);
Queue.front();              // 1
LinkedListQueue.enqueue(1);
LinkedListQueue.front();    // { val: 1, next: null }

. . . . .

rear()

Returns the last element or node from the data property. Returns undefined or null if there are no elements.

Queue.enqueue(1, 2);
Queue.rear();                  // 2
LinkedListQueue.enqueue(1, 2);
LinkedListQueue.rear();        // { val: 2, next: null }

. . . . .

search(value)

Returns the element or node from the data property if it exists. Returns null if there are no elements.

Queue.enqueue(1);
Queue.search(1);              // 1
Queue.search(3);              // null
LinkedListQueue.enqueue(1);
LinkedListQueue.search(1);    // { val: 1, next: null }
LinkedListQueue.search(3);    // null

. . . . .

length()

Returns the length of the data property. If a LinkedList object is empty, it will still have a length of 1, since it still technically has a node: { val: null, next: null }.

Queue.enqueue(1);
Queue.length();    // 1
Queue.dequeue();
Queue.length();    // 0
LinkedListQueue.enqueue(1);
LinkedListQueue.length();   // 2
LinkedListQueue.dequeue();
LinkedListQueue.length();   // 1

Stack

Stacks are almost identical to the Queue objects in Plus. There are also only two initialization options for the data storage, just like in a Queue object: an array, or a linked list.

Methods

constructor(data = null)

Initialize a new Stack object. Possible parameter(s) are: 'linkedlist'.

let Stack = new Plus.Stack();
let Stack = new Plus.Stack('linkedlist');

The returned Stack object has the following structure:

{
  data: [] || 'Linked List',
  ll: true || false
}

. . . . .

push(...arguments)

Appends element(s) to the end of the data property. To pass several elements at once, simply separate each element by a comma.

Stack.push(1);
Stack.push(2, 3, 4);
Stack.push('string', true, [1, 2, 3], { one: 'more' });

. . . . .

pop()

Removes and returns the last element from the data property. Returns null if the store is empty.

Stack.push(1);
Stack.pop();  // 1
Stack.pop();  // null

. . . . .

peek()

Returns the last element or node from the data property. Returns undefined or null if there are no elements.

Stack.push(1, 2);
Stack.peek();              // 2
LinkedListStack.push(1, 2);
LinkedListStack.peek();    // { val: 2, next: null }

. . . . .

isEmpty()

Returns true || false based on whether the data property has data or not.

Stack.push(1, 2);
Stack.isEmpty();  // false
Stack.pop();
Stack.pop();
Stack.isEmpty();  // true

. . . . .

search(value)

Returns the element or node from the data property if it exists. Returns null if there are no elements.

Stack.push(1);
Stack.search(1);              // 1
Stack.search(3);              // null
LinkedListStack.push(1);
LinkedListStack.search(1);    // { val: 1, next: null }
LinkedListStack.search(3);    // null

. . . . .

length()

Returns the length of the data property. If a LinkedList object is empty, it will still have a length of 1, since it still technically has a node: { val: null, next: null }.

Stack.push(1);
Stack.length();    // 1
Stack.pop();
Stack.length();    // 0
LinkedListStack.push(1);
LinkedListStack.length();   // 2
LinkedListStack.pop();
LinkedListStack.length();   // 1

Linked List

The Linked List object is exactly what a developer would expect: a head node with a single next pointer to the next node or null.

Methods

constructor(value = null)

Initialize a new Linked List object. Possible parameter(s) are any valid data in JavaScript. May or may not be initialized with a value.

let NoValueLinkedList = new Plus.LinkedList(); // { head: { val: null, next: null }}
let LinkedList = new Plus.LinkedList(3);       // { head: { val: 3, next: null }}

The returned Linked List object has the following structure:

{
  head: {
    val: null,
    next: null
  },

  size: 1
}

. . . . .

assignHeadValue(value = null)

Assigns the head node's value to the passed parameter. This method can be used in the case that the Linked List object is initialized without a value, or when the first node's value should be changed.

LinkedList.assignHeadValue(4);                  // { head: { val: 4, next: null }, size: 1 }
LinkedListWithData.assignHeadValue([1, 2, 3]);  // { head: { val: [1, 2, 3], next: [Object] }, size: 2 }

. . . . .

insert(...newData)

Inserts elements of ...newData as nodes to the tail of the linked list. Returns this for daisy-chaining.

LinkedList.insert(1); // { head: { val: 2, next: { val: 1, next: null }}}
LinkedList.insert(2, 3); 
/* 
{ head: { 
      val: 2, next: { 
        val: 1, next: {
          val: 2, next: {
            val: 3, next: null
        }
      } 
    }
  },

  size: 4
}
*/

. . . . .

insertAtIndex(index, ...newData)

Inserts elements of ...newData as nodes at the passed index of the linked list. Does not overwrite nodes already in the linked list. Returns this for daisy-chaining.

LinkedList = new Plus.LinkedList(4);
LinkedList.insertAtIndex(0, 2, true); // { head: val: 4, next: { val: 2, next: { val: true, next: null }}}

. . . . .

removeByValue(value)

Removes the first node with given value and returns value. Returns null if the value is not found.

LinkedList.insert(2, 3, 4);
LinkedList.removeByValue(3); // 3
LinkedList.removeByValue(3); // null

. . . . .

removeByIndex(index)

Removes the first node with given value and returns value. Returns null if the index is not found, the index is not a number, or the index is less than -1.

LinkedList.assignHeadValue(4);
LinkedList.removeByIndex(-1);   // null
LinkedList.removeByIndex('0');  // null
LinkedList.removeByIndex(0);    // 4

. . . . .

getNodeAtIndex(index)

Returns the node at the given index. Returns null if the index is not found.

LinkedList.assignHeadValue(4);
LinkedList.getNodeAtIndex(1);   // null
LinkedList.getNodeAtIndex(0);   // { val: 4, next: null }

. . . . .

getNodeIndexByValue(value)

Returns the first node and index for the given value.

LinkedList.assignHeadValue(4);
LinkedList.getNodeIndexByValue(1);   // null
LinkedList.getNodeIndexByValue(4);   // { node: { val: 4, next: null }, index: 0 }

The returned object has the following structure:

{ 
  node: { val: null, next: null }, // this is the returned node
  index: null                      // this is the index of that node
}

. . . . .

updateValueAtIndex(index, value)

Updates the val property of the node at the given index. Returns this || null depending on the success of the invocation.

LinkedList.assignHeadValue(4);
LinkedList.updateValueAtIndex(0, true);  // { head: { val: true, next: null }, size: 1 }
LinkedList.updateValueAtIndex(4, false); // null

. . . . .

getMiddleNode()

Returns the node in the middle of the Linked List object. Returns undefined for a list with no middle.

LinkedList.assignHeadValue(4);
LinkedList.insert(1, 2, 3, 5);
LinkedList.getMiddleNode(); // { val: 2, next: [Object] }

. . . . .

tail()

Returns the last node in the Linked List object.

LinkedList.assignHeadValue(4);
LinkedList.tail(); // { val: 4, next: null }
LinkedList.insert(2);
LinkedList.tail(); // { val: 2, next: null }

. . . . .

removeByTail()

Removes the last node in the Linked List object. Returns value from deleted node.

LinkedList.assignHeadValue(4);
LinkedList.removeByTail(); // 4
LinkedList.assignHeadValue(4).insert(1, 2);
LinkedList.removeByTail(); // 2

. . . . .

toArray()

Returns [] comprised of the values from the nodes in the Linked List object, starting from the head and ending with the tail.

LinkedListEmpty.toArray(); // [];
LinkedList.assignHeadValue(4);
LinkedList.toArray();      // [4];
LinkedList.insert(2, 3);   // [4, 2, 3];

. . . . .

reverse()

Returns this and destructively reverses the nodes in the Linked List object, starting from the head and ending with the tail.

LinkedList.assignHeadValue(4);
LinkedList.insert(2, 3);
LinkedList.reverse(); // { head: { val: 3, next: { val: 2, next: { val: 4, next: null }}}, size: 3 }

. . . . .

clear()

Returns this and destructively clears the nodes in the Linked List object.

LinkedList.clear(); // { head: { val: undefined, next: null }, size: 1 }

. . . . .

contains(value)

Returns true || false depending on whether the passed value can be found in the Linked List object.

LinkedList.assignHeadValue(4);
LinkedList.contains(4); // true
LinkedList.contains(1); // false

. . . . .

length()

Returns this.size, which is a count of the nodes in the Linked List object. This will always be an integer greater than or equal to 1.

LinkedList.assignHeadValue(4);
LinkedList.length(); // 1
LinkedList.insert(2, 3);
LinkedList.length(); // 3
LinkedList.removeByValue(2);
LinkedList.length(); // 2
LinkedList.removeByValue(1);
LinkedList.length(); // 1
LinkedList.removeByValue(3);
LinkedList.length(); // 1

. . . . .

count(value = null)

Returns count of how many nodes in the Linked List object have a val property with value.

LinkedList.assignHeadValue(4);
LinkedList.count();       // null
LinkedList.count(4);      // 1
LinkedList.count(1);      // 0
let arr = [1, 2];
LinkedList.insert(arr);
LinkedList.count(arr);    // 1
LinkedList.count([1, 2]); // 0

. . . . .

countMultiple(...values)

Returns an object with properties which represent the count of that given property in the Linked List object. The value must be deeply equal to the val property of a given node. Only strings and numbers may be used as values. Use count(value) for getting the count of specific objects.

LinkedList.assignHeadValue(4);
LinkedList.insert(3, 'one', 'one', 1, 'two', ['one']);
LinkedList.countMultiple(4, 3, 'one', 'two', 2, { one: 'yes' }, ['one']); 
// { 4: 1, 3: 1, 'one': 2, 'two': 1, 2: 0 }

Binary Tree

The main difference between BinaryTree and BST objects are that the former have no data constraints. This means that any data can be inserted into the tree; however, the BST object enforces data consistency which creates O(log2n) search, insert, and removal times.

Methods

constructor(array = [1])

Initialize a new BinaryTree object. Possible parameter value(s) are: [].

Use undefined for nodes in the tree which should be null.

let BinaryTree = new Plus.BinaryTree([2, 1, 3]);
let BinaryTree = new Plus.BinaryTree([1, 2, 3, 4, 5, 6, undefined, undefined, undefined, 8]);

The returned BinaryTree object has the following structure:

// 1

{
  root: { 
          val: 2, 
          left: { val: 1, left: null, right: null}, 
          right: { val: 3, left: null, right: null }
        } 
}

// 2
{
  root: { 
    val: 1,
      left: 
       { val: 2,
         left: { val: 4, left: [Object], right: [Object], height: 0 },
         right: { val: 5, left: [Object], right: null, height: 0 },
         height: 0 },
      right: 
       { val: 3,
         left: { val: 6, left: null, right: null, height: 0 },
         right: { val: null, left: null, right: null, height: 0 },
         height: 0 },
      height: 0 }
}

// Pay attention to the placement of null nodes.

Nodes are inserted in level-order, meaning that the number of nodes possible for a given level dictates where each node is placed. The first level, the root, has one possible node, so the first element of [1, 2, 3, undefined...] is converted to a node in that level. The next level has two possible nodes, so the next two values in the array are the left and right nodes of the root node. Each level doubles in size.

Since the placement of nodes is entirely up the [] passed in as the parameter, it is possible that the binary tree will have nodes attached to a node with a null value. This may cause problems with searching for values in certain cases. For absolute certainty in the validity of the tree structure, use the BST object.

. . . . .

insert(value)

Replaces a null value in either the left or right property with a new node with passed value. Only one element may be passed at a time. left is evaluated for a null before right.

Returns this for daisy chaining.

BinaryTree; 
/*
{ 
  root: {
    val: 2,
    left: null,
    right: null
  } 
}
*/
BinaryTree.insert(2).insert(3);
/*
{ 
  root: {
    val: 2,
    left: { val: 2, left: null, right: null },
    right: { val: 3, left: null, right: null }
  } 
}
*/

The value is inserted in level-order, meaning that the first node in the level with either a null left or right is replaced with a new TreeNode with the passed value.

. . . . .

remove(value)

Removes the first node with the passed value and returns this for daisy chaining. Will not return null if the given value cannot be found.

BinaryTree;
/*
{ 
  root: {
    val: 2,
    left: null,
    right: null
  } 
}
*/
BinaryTree.insert(2).insert(3).remove(3);
/*
{
  root: {
    val: 1,
    left: { val: 2, left: null, right: null }
    right: null
  }
}
*/

. . . . .

getNode(value)

Returns the first node with the passed value. Will return null if the node cannot be found.

BinaryTree;
/*
{
  root: {
    val: 1,
    left: { val: 2, left: null, right: null }
    right: null
  }
}
*/
BinaryTree.getNode(2);
// { val: 2, left: null, right: null }

. . . . .

findHeight(node)

Returns a number representing the height of the passed node. Throws an error if the passed node does not have TreeNode as its prototype object.

 
let BinaryTree = new Plus.BinaryTree([10, 20, 
                                      30, undefined, 
                                      undefined, undefined, 
                                      40]);
let node = BinaryTree.getNode(30);
BinaryTree.findHeight(node); // 1

. . . . .

findMaxDepth()

Returns a number representing the maximum depth of this.root.

let arr = [1, 2, 3, 4, 5, 6, 7, 8];
let BinaryTree = new Plus.BinaryTree(arr);
BinaryTree.findMaxDepth(); // 4

. . . . .

getValuesTraversal(type = 'post')

Returns an [] representing the elements in a certain order traversal. The possible options are in: ['post', 'pre', 'in']. Will not include null values in the return value.

let BinaryTree = new Plus.BinaryTree(1);
BinaryTree.insert(2).insert(3);
BinaryTree.getValuesTraversal();      // [2, 3, 1]
BinaryTree.getValuesTraversal('pre'); // [1, 2, 3]
BinaryTree.getValuesTraversal('in');  // [2, 1, 3]

. . . . .

manipulateTraversal(func, type = 'post')

Mutates this.root with the passed function, func, in whatever order designated by the passed type parameter. The possible options for type are: ['post', 'pre', 'in']. Returns this which makes it daisy chainable.

const double = (node) => {
  return node.val = node.val * 2;
};

let BinaryTree = new Plus.BinaryTree(1);
BinaryTree.insert(2).insert(3);
BinaryTree.manipulateTraversal(double); 
BinaryTree.getValuesTraversal();       // [2, 3, 1]

Binary Search Tree

BST objects are self-balancing, meaning that the difference in height between the left and right branches of a given node cannot be less than -1 or greater than 1.

The type of Binary Search Tree used in this class is an AVL Tree.

All nodes in the tree must have unique values.

Methods

constructor(dataType, options)

Initialize a new BST object.

The dataType parameter represents the single type of data that the initialized BST object can store. The possible options are in the following array and correspond to the actual primitive and/or object in vanilla JavaScript: ['number', 'string', 'date', 'object']. Only pass one string, otherwise an error will be thrown.

The options parameter represents an optional object which may be passed into the constructor function to further customize the way data is handled in the BST object. The only properties available to this object are in the following arrays: ['key', 'keyType', 'compareFunction'] for 'object' typed trees, and ['compareFunction'] for ['number', 'string', 'date'] typed trees.

// For Date, String, or Number BSTs

let options = { compareFunction: exampleFunc };

// For Object

let options = { 
  key: 'bigId',
  keyType: 'number',
  compareFunction: sortByIdOrSomething 
};

key represents the property that will be on every object passed into the BST object. This key is then used to sort and balance the tree as elements are inserted and removed. This must be a string.

keyType represents the type of primitive data that will be stored in the key property of each object. The available options are in the following array: ['string', 'number']. Incorrect values will result in thrown errors.

compareFunction represents the function which will be used to determine if one value is less than another value. Using this, the tree will insert, remove, and rebalance itself. This can be passed with any data type, not just object.

The function must come in the following form:

// this example would work for strings

const exmapleCompareForStrings = function(a, b) {
  return a.length < b.length;  
};

// this example would work for an object with key: id

const sortById = function(a, b) { // this works for objects
  return a.id < b.id;
};

// this example would work for a number BST

const sortByDivision = function(a, b) {
  return (a / 2) < (b / 3);  
};

// Notice that the expression must be: a < b.

BST objects may be instantiated as shown in the following code snippet:

let StringBST = new Plus.BST('string');
let NumberBST = new Plus.BST('number');
let DateBST = new Plus.BST('date', { compareFunction: sortByDay });
let ObjectBST = new Plus.BST('object', {
  key: 'id',
  keyType: 'number',
  compareFunction: sortById  
});

// String and Number BSTs can also be passed compareFunction.

The returned BST object has the following structure:

{
  type: dataType,        // determines valid data
  compareFunction: func, // for all data
  key: undefined,        // for objects
  keyType: undefined,    // for objects
  duplicates: {},        // prevents duplicates
  size: 0,               // allows for constant time tree size lookup
  root: null             // this is where the tree is stored
}

. . . . .

insert(values)

Inserts node(s) with the passed value property. To pass several elements at once, pass an [] with the elements separated with commas.

let NumberBST = new Plus.BST('number');
NumberBST.insert(1); 
NumberBST.insert([2, 3]).insert(5); // can chain methods, too
/*
{
  root: {
    val: 2,
    left: { val: 1, left: null, right: null },
    right: { val: 3, left: null, right: { val: 5, left: null, right: null }}
  }
}
*/

. . . . .

remove(values)

Removes node(s) with the passed value property. To pass several elements at once, pass an [] with the elements separated with commas. Returns this, so methods can be chained after its invocation.

let DateBST = new Plus.BST('date');
DateBST.insert([new Date('November 15, 2020'),
                new Date('December 25, 2020'),
                new Date('March 25, 2020'),
                new Date('July 4, 2029')]);
DateBST.remove(new Date('July 4, 2029'));
/*
{
  root: {
    val: December 25, 2020     // not real formatting
    left: November 14, 2020,   // not real formatting
    right: March 25,, 2020     // not real formatting
  }
}
*/

. . . . .

maxValue(root = this.root)

Returns the node with the greatest val property.

let ObjectBST = new Plus.BST('object', {
  key: 'id',
  keyType: 'number',
  compareFunction: sortById  
});

ObjectBST.insert([
  { id: 1 },
  { id: 2 },
  { id: 3 }
]);

ObjectBST.maxValue(); // { id: 3 }

. . . . .

minValue(root = this.root)

Returns the node with the smallest val property.

let ObjectBST = new Plus.BST('object', {
  key: 'id',
  keyType: 'number',
  compareFunction: sortById  
});

ObjectBST.insert([
  { id: 1 },
  { id: 2 },
  { id: 3 }
]);

ObjectBST.minValue(); // { id: 1 }

. . . . .

search(value, root = this.root)

Returns the node from this.root with the passed value if it exists. Returns null if there are no elements which match the passed value.

Objects will be matched with the toString() method, so deep equality is not necessary for the search method to return the correct node.

let ObjectBST = new Plus.BST('object', {
  key: 'id',
  keyType: 'number',
  compareFunction: sortById  
});

ObjectBST.insert([
  { id: 1 },
  { id: 2 },
  { id: 3 }
]);

ObjectBST.search({ id: 1 }); // { id: 1 }

. . . . .

length()

Returns this.size, which is the number of nodes in the tree.

let StringBST = new Plus.BST('string');
StringBST.insert(['coal', 'mining', 'is', 'no', 'fun']);
StringBST.length(); // 5
StringBST.remove('coal').remove('mining');
StringBST.length(); // 3
StringBST.remove(['is', 'no']);
StringBST.length(); // 1

. . . . .

contains(value)

Returns true || false, depending on if value is a property on this.duplicates with true value.

let NumberBST = new Plus.BST('number');
NumberBST.insert([1, 2, 3]);
NumberBST.contains(4); // false
NumberBST.contains(1); // true

. . . . .

isEmpty()

Returns true || false, depending on if this.root is null.

let NumberBST = new Plus.BST('number');
NumberBST.isEmpty(); // true

NumberBST.insert([1, 2, 3]);
NumberBST.isEmpty(); // false

. . . . .

getValuesTraversal(type = 'post')

Returns an [] representing the elements in a certain order traversal. The possible options are in: ['post', 'pre', 'in']. Will not include null values in the return value.

let NumberBST = new Plus.BST('number');
NumberBST.insert([1, 2, 3, 4]);
NumberBST.getValuesTraversal(); // [1, 4, 3, 2]

Graph

The Graph object in DS-Plus takes the form of an Adjacency List, which is an efficient implementation of a graph. Vertices are stored as keys in an object for O(1) lookup time.

Methods

constructor(dataType, direction)

Initialize a new Graph object.

let Graph = new Plus.Graph('number', 'one');
let GraphBi = new Plus.Graph('number', 'two');

The returned Graph object has the following structure:

{
  data: {},
  type: 'string' || 'number' || 'object'
  size: 0,
  way: 'one' || 'two'
}

The dataType parameter can take either of the following options: ['string', 'number', 'object']. As one can guess, these are the three kinds of data that can be stored in the data property of the Graph object.

The direction parameter can take either of the following options: ['one', 'two']. This parameter determines the whether or not an edge is bi-directional or uni-directional.

If 'one' is selected, an edge will only go in one direction. Check the following example to see the difference between 'one' and 'two'.

let Graph = new Plus.Graph('number', 'one');
Graph.addVertices(2, 3, 4);
Graph.addEdges(2, [3, 4]);
Graph.getEdges(3); // [], no edges
Graph.getEdges(2); // [3, 4]

let GraphBi = new Plus.Graph('number', 'two');
Graph.addVertices(2, 3, 4);
Graph.addEdges(2, [3, 4]);
Graph.getEdges(3); // [2]
Graph.getEdges(2); // [3, 4]

. . . . .

addVertices(...vertices)

Inserts vertice(s) to the data property as keys. The keys will have [] value by default. To pass several elements at once, simply separate each element by a comma.

Objects passed into this method will be converted to strings with JSON.stringify(obj).

Errors will be thrown for invalid data or already existing vertices being passed into this method.

Returns this for method chaining.

let Graph = new Plus.Graph('object', 'one');
Graph.addVertices({ id: 0 }, { id: 1, some: 'info' });
Graph.data; // { 'JSON-stringified-object': [], 'JSON-stringified-object': [] };

. . . . .

removeVertex(vertex)

Removes and returns the vertex that was passed into the method. This will mutate the other vertexes accordingly and requires no repointing on the developer's end.

let Graph = new Plus.Graph('object', 'one');
Graph.addVertices({ id: 0 }, { id: 1, some: 'info' });
Graph.addEdges({ id: 0 }, [{ id: 1, some: 'info' }]);
Graph.removeVertice({ id: 1, some: 'info' });
Graph.getEdges({ id: 0 }); // []

let GraphBi = new Plus.Graph('number', 'two');
GraphBi.addVertices(1, 2, 3, 4);
GraphBi.addEdges(1, [2, 3]);
GraphBi.getEdges(1); // [2, 3]
GraphBi.getEdges(2); // [1]

GraphBi.removeVertex(1);
GraphBi.getEdges(2); // [] // removed edge to 1
GraphBi.getEdges(3); // [] // removed edge to 1

. . . . .

addEdges(vertex, arr)

Inserts edges from arr for the passed vertex and returns this for method chaining.

Errors will be thrown for incorrect data, missing parameters, or if arr is not an Array object.

let Graph = new Plus.Graph('object', 'two');
Graph.addVertices({ id: 0 }, { id: 1, some: 'info' });
Graph.addEdges({ id: 0 }, [{ id: 1, some: 'info' }]);
Graph.getEdges({ id: 0 });               // [{ id: 1, some: 'info' }]
Graph.getEdges({ id: 1, some: 'info' }); // [{ id: 0 }]

let GraphBi = new Plus.Graph('number', 'one');
GraphBi.addVertices(1, 2, 3, 4);
GraphBi.addEdges(1, [2, 3]);
GraphBi.getEdges(1); // [2, 3]
GraphBi.getEdges(2); // []

. . . . .

removeEdges(vertex, arr)

Removes edges from arr for the passed vertex and returns this for method chaining.

Errors will be thrown for incorrect data, missing parameters, or if arr is not an Array object.

let Graph = new Plus.Graph('object', 'two');
Graph.addVertices({ id: 0 }, { id: 1, some: 'info' });
Graph.addEdges({ id: 0 }, [{ id: 1, some: 'info' }]);
Graph.removeEdges({ id: 1, some: 'info' }, [{ id: 0 }]);
Graph.getEdges({ id: 1, some: 'info' }); // []
Graph.getEdges({ id: 0 });               // []

let GraphBi = new Plus.Graph('number', 'one');
GraphBi.addVertices(1, 2, 3, 4);
GraphBi.addEdges(1, [2, 3]);
GraphBi.removeEdges(1, [2]);
GraphBi.getEdges(1); // [3]

. . . . .

getSize()

Returns the number of vertices in the Graph object.

let Graph = new Plus.Graph('string', 'one');
Graph.getSize(); // 0
Graph.addVertices('one', 'two', 'three');
Graph.getSize(); // 3
Graph.removeVertex('one');
Graph.getSize(); // 2

. . . . .

getEdges(vertex)

Returns the [] of edges for the passed vertex.

Errors will be thrown for vertices which are not in the data property.

let Graph = new Plus.Graph('object', 'two');
Graph.addVertices({ id: 0 }, { id: 1, some: 'info' });
Graph.addEdges({ id: 0 }, [{ id: 1, some: 'info' }]);
Graph.getEdges({ id: 0 });               // [{ id: 1, some: 'info' }]
Graph.getEdges({ id: 1, some: 'info' }); // [{ id: 0 }]

let GraphBi = new Plus.Graph('number', 'one');
GraphBi.addVertices(1, 2, 3, 4);
GraphBi.addEdges(1, [2, 3]);
GraphBi.getEdges(1); // [2, 3]
GraphBi.getEdges(2); // []

. . . . .

numberOfEdges(vertex)

Returns the number of elements in [] of the passed vertex.

null will be returned for vertices which are not in the data property.

let Graph = new Plus.Graph('object', 'two');
Graph.addVertices({ id: 0 }, { id: 1, some: 'info' });
Graph.addEdges({ id: 0 }, [{ id: 1, some: 'info' }]);
Graph.getEdges({ id: 0 });               // [{ id: 1, some: 'info' }]
Graph.getEdges({ id: 1, some: 'info' }); // [{ id: 0 }]
Graph.numberOfEdges({ id: 0 }); // 1

let GraphBi = new Plus.Graph('number', 'one');
GraphBi.addVertices(1, 2, 3, 4);
GraphBi.addEdges(1, [2, 3]);
GraphBi.getEdges(1); // [2, 3]
GraphBi.getEdges(2); // []
GraphBi.numberOfEdges(1); // 2

. . . . .

hasEdge(vertexOne, vertexTwo)

Returns true || false based on if vertexOne has vertexTwo as one of its edges.

Errors will be thrown for vertices which are not in the data property.

let Graph = new Plus.Graph('object', 'two');
Graph.addVertices({ id: 0 }, { id: 1, some: 'info' });
Graph.addEdges({ id: 0 }, [{ id: 1, some: 'info' }]);
Graph.hasEdge({ id: 0 }, { id: 1, some: 'info' }); // true

let GraphBi = new Plus.Graph('number', 'one');
GraphBi.addVertices(1, 2, 3, 4);
GraphBi.addEdges(1, [2, 3]);
GraphBi.hasEdge(1, 2); // true
GraphBi.hasEdge(1, 4); // false

. . . . .

hasVertex(vertex)

Returns true || false based on if vertex is a property in the data object.

let Graph = new Plus.Graph('object', 'two');
Graph.addVertices({ id: 0 }, { id: 1, some: 'info' });
Graph.hasVertex({ id: 0 }); // true
Graph.hasVertex({ id: 2 }); // false

let GraphBi = new Plus.Graph('number', 'one');
GraphBi.addVertices(1, 2, 3, 4);
GraphBi.hasVertex(1); // true
GraphBi.hasVertex(0); // false

. . . . .

edgesToArray(vertex)

Returns [[vertex, edgeOne], [vertex, edgeTwo] ...] based on the [] for a given vertex. Essentially, it will return sub-arrays of all the pairs of edges possible for a given vertex.

Errors will be thrown for vertices which are not in the data property.

let Graph = new Plus.Graph('object', 'two');
Graph.addVertices({ id: 0 }, { id: 1, some: 'info' });
Graph.addEdges({ id: 0 }, [{ id: 1, some: 'info' }]);
Graph.edgesToArray({ id: 0 }); // [[{ id: 0 }, { id: 1, some: 'info' }]]

let GraphBi = new Plus.Graph('number', 'one');
GraphBi.addVertices(1, 2, 3, 4);
GraphBi.addEdges(1, [2, 3]);
GraphBi.edgesToArray(1); // [[1, 2], [1, 3]]