1.1.2 • Published 7 years ago

differentia v1.1.2

Weekly downloads
4
License
MIT
Repository
github
Last release
7 years ago

Differentia.js

NPM

This library provides a basic suite of Object/Array focused functions. They are all "deep" algorithms, and fully traverse all child Objects/Arrays/properties unless given a search index object with specifies otherwise.

:closed_book: Documentation


:page_facing_up: Supported Data Types

DataTypeCloneDiff
Function:x::x:
Symbol:x::x:
Blob:x::x:
Object:white_check_mark::white_check_mark:
Array:white_check_mark::white_check_mark:
String:white_check_mark::white_check_mark:
Number:white_check_mark::white_check_mark:
Boolean:white_check_mark::white_check_mark:
RegExp:white_check_mark::white_check_mark:

Search Algorithm Iterators

The search iterators, bfs and dfs, are actually both the same searchIterator algorithm (See CONTRIBUTING.md for more details about searchIterator) with differing traversal scheduling data structures (Queue VS Stack).

Upon calling next(), the search iterators expose a single state object in value which encapsulates the current state of iteration/traversal. The object is a flyweight and is thus mutated between every iteration/traversal; because of this, do not attempt to store or otherwise rely on values contained within it for more than one step in the iteration.

PropertyDatatypeDescription
accessorMixedThe accessor being used to access value.tuple.subject during property/element enumerations. Equal to state.accessors[state.iteration].
accessorsArrayAn Array of enumerable acessors found in value.tuple.search.
currentValueMixedThe value of the element of enumeration. Equal to value.tuple.subject[value.accessor].
existingnull or ObjectIf dfs encounters an Object/Array it has seen before during the same search, this property will be set to the equivalent tuple; otherwise it will be null. Objects added to that tuple previously will show up again here.
isContainerBooleanIndicates if the current item of the enumeration is an Object or Array.
isFirstBooleanIndicates if the current item of the enumeration is the first item to be enumerated.
isLastBooleanIndicates if the current item of the enumeration is the last item to be enumerated.
iterationsNumberA number indicating how many items have been enumerated in the current Object/Array. Gets reset to 0 on each traversal.
lengthNumberThe total number of enumerable properties/elements of the current Object/Array being enumerated.
noIndexBooleanIndicates if a search index was not given. If true, then search is equal/assigned to subject.
targetTuplesArrayA list of tuples to be targeted for traversal. Tuples are removed from the bottom-up.
traverseBooleanIndicates if the current item of enumeration should be traversed.
tupleObjectAn Object containing all Objects being traversed in parallel.

The tuple object contains the following properties:

PropertyDatatypeDescription
subjectObject/ArrayThe source of paths/elements for traversal/enumeration.
searchObject/ArrayThe source of target paths/elements for traversal/enumeration.

Traversal is performed upon this tuple of objects equally, providing they have overlapping/equal paths. If any node exists in search that does not exist in any one object of the tuple, then traversal is aborted for that specific object and it is dropped from the tuple; except if the object lacking the node is subject, in which case traversal is aborted completely across all objects of the tuple, and nothing is dropped from the tuple.

dfs

Generator

dfs( subject, search = null ] );

An implementation of Depth-First Search. Enumerates properties/elements in subject, traversing into any Objects/Arrays, using search as a search index. Any properties/nodes present in search will be used to enumerate, traverse, and access the properties/nodes of subject. If a property/node exists in search that does not exist in subject, or vice versa, it will be skipped.

Upon calling next(), the dfs iterator exposes a single value object which encapsulates the state of iteration/traversal at the time of being returned. The object is a flyweight and is thus mutated between every iteration/traversal; because of this, do not attempt to store or otherwise rely on values contained within it.

Parameters

  • subject Object/Array

    The root Object or Array to enumerate & traverse.

  • search (Optional) Object/Array

    An Object or Array specifying the properties to traverse and enumerate. All other properties are ignored.

Examples

var subject = {
  greetings1: [
    "Hello World!"
  ],
  greetings2: [
    "Good Morning!"
  ]
};

var search = differentia.dfs(subject, subject);

// Starts on the top layer of the root of subject:
var iteration = search.next();
console.log(iteration.value.accessor); // Logs "greetings1"
console.log(iteration.value.currentValue); // Logs ["Hello World!"]
iteration = search.next();
console.log(iteration.value.accessor); // Logs "greetings2"
console.log(iteration.value.currentValue); // Logs ["Good Morning!"]

// Finished enumerating root Object...
// Now it will traverse and enumerate Objects/Arrays it saw in reverse order:
iteration = search.next();
console.log(iteration.value.accessor); // Logs 0
console.log(iteration.value.currentValue); // Logs "Good Morning!"
iteration = search.next();
console.log(iteration.value.accessor); // Logs 0
console.log(iteration.value.currentValue); // Logs "Hello World!"
var subject = {
  greetings1: [
    "Hello World!"
  ],
  greetings2: [
    "Good Morning!"
  ]
};

var search = {
  greetings2: {
    0: null
  }
};

var search = differentia.dfs(subject, search);

// Starts on the top layer of the root of subject:
var iteration = search.next();
console.log(iteration.value.accessor); // Logs "greetings2"
console.log(iteration.value.currentValue); // Logs ["Good Morning!"]

// Finished enumerating root Object...
// Now it will traverse and enumerate Objects/Arrays it saw:
iteration = search.next();
console.log(iteration.value.accessor); // Logs 0
console.log(iteration.value.currentValue); // Logs "Good Morning!"

bfs

Generator

bfs( subject [, search = null ] );

An implementation of Breadth-First Search. Enumerates properties/elements in subject, traversing into any Objects/Arrays, using search as a search index. Any properties/nodes present in search will be used to enumerate, traverse, and access the properties/nodes of subject. If a property/node exists in search that does not exist in subject, or vice versa, it will be skipped.

Parameters

  • subject Object/Array

    The root Object or Array to enumerate & traverse.

  • search (Optional) Object/Array

    An Object or Array specifying the properties to traverse and enumerate. All other properties are ignored.

Examples

var subject = {
  greetings1: [
    "Hello World!"
  ],
  greetings2: [
    "Good Morning!"
  ]
};

var search = differentia.bfs(subject, subject);

// Starts on the top layer of the root of subject:
var iteration = search.next();
console.log(iteration.value.accessor); // Logs "greetings1"
console.log(iteration.value.currentValue); // Logs ["Hello World!"]
iteration = search.next();
console.log(iteration.value.accessor); // Logs "greetings2"
console.log(iteration.value.currentValue); // Logs ["Good Morning!"]

// Finished enumerating root Object...
// Now it will traverse and enumerate Objects/Arrays it saw in-order:
iteration = search.next();
console.log(iteration.value.accessor); // Logs 0
console.log(iteration.value.currentValue); // Logs "Hello World"
iteration = search.next();
console.log(iteration.value.accessor); // Logs 0
console.log(iteration.value.currentValue); // Logs "Good Morning"
var subject = {
  greetings1: [
    "Hello World!"
  ],
  greetings2: [
    "Good Morning!"
  ]
};

var search = {
  greetings2: {
    0: null
  }
};

var search = differentia.bfs(subject, search);

// Starts on the top layer of the root of subject:
var iteration = search.next();
console.log(iteration.value.accessor); // Logs "greetings2"
console.log(iteration.value.currentValue); // Logs ["Good Morning!"]

// Finished enumerating root Object...
// Now it will traverse and enumerate Objects/Arrays it saw:
iteration = search.next();
console.log(iteration.value.accessor); // Logs 0
console.log(iteration.value.currentValue); // Logs "Good Morning!"

Main Functions

clone

Function

clone( subject [, search = null ] );

Returns a clone of subject. If search is provided, the clone will only contain properties/paths that are present in search.

Parameters

  • subject Object/Array

    The Object or Array to clone from.

  • search (Optional) Object/Array

    An Object or Array specifying the properties to traverse and enumerate. All other properties are ignored.

Examples

var subject = {
 string1: "Hello",
 string2: "World!"
};

var clonedObject = differentia.clone(subject);
console.log(clonedObject); // Logs {string1: "Hello", string2: "World!"}
var subject = {
 string1: "Hello",
 string2: "World!"
};

var search = {
  string2: null
};

var clonedObject = differentia.clone(subject search);
console.log(clonedObject); // Logs {string2: "World!"}

diffClone

Function

diffClone( subject , compared [, search = null ] );

Returns a clone of subject, containing only the properties which differ from those contained within compared.

Parameters

  • subject Object/Array

    The Object or Array to clone from.

  • compared Object/Array

    The Object or Array to compare subject to.

  • search (Optional) Object/Array

    An Object or Array specifying the properties to traverse and enumerate. All other properties are ignored.

Examples

// The Object to clone from:
var subject = {
 string1: "Hello",
 string2: "Bob",
 string3: "Ross!"
};

// The Object to compare `objectToClone` to:
var compared = {
 string1: "Hello",
 string2: "World!"
};

 var clonedObject = differentia.diffClone(subject, compared);

 /*
 Variable `clonedObject` is now this Object:
 {
  string2: "Bob",
  string3: "Ross!"
 }
 */
var subject = {
 string1: "Burn the",
 string2: "Pretty",
 string3: "Little",
 string4: "Trees"
};

var compared = {
 string1: "Hello",
 string2: "World!"
};

// Here, we ignore `string1`.
var search = {
 string2: null,
 string3: null,
 string4: null
};

var clonedObject = differentia.diffClone(subject, compared, search);

/*
Variable `clonedObject` is now this Object:
{
  string2: "Pretty",
  string3: "Little",
  string4: "Trees"
}
*/

diff

Function

diff( subject , compared [, search = null ] );

Returns true if compared's structure, properties, or values differ in any way from subject, or false if otherwsie.

Parameters

  • subject Object/Array

    The Object or Array to compare compared to.

  • compared Object/Array

    The Object or Array to compare to subject.

  • search (Optional) Object/Array

    An Object or Array specifying the properties to traverse and enumerate. All other properties are ignored.

Examples

//
var subject = {
  string1: "Pretty",
  array1: [
    "Little Clouds",
    "Little Trees"
  ]
};

var compared = {
  string2: "Pretty",
  array1: [
    "Little Branches",
    "Little Leaves"
  ]
};

var doTheyDiffer = differentia.diff(subject, compared);
/*
`doTheyDiffer` is now `true`.
*/
var subject = {
  string1: "Pretty",
  array1: [
    "Little Clouds",
    "Little Trees"
  ]
};

var compared = {
  string2: "Pretty",
  array1: [
    "Little Clouds",
    "Autumn Day"
  ]
};

// Here, we ignore index `1` of `array1`.
var search = {
  string1: "",
  array1: [
    0: ""
  ]
};

var doTheyDiffer = differentia.diff(subject, compared, search);
/*
`doTheyDiffer` is now `false`.
*/

deepFreeze

Function

deepFreeze( subject [, search = null ] );

Traverses and enumerates subject, freezing it and it's children. Uses Object.freeze(). Returns the frozen Object/Array. The method directly mutates the Object/Array.

Parameters

  • subject Object/Array

    The Object or Array to freeze.

  • search (Optional) Object/Array

    An Object or Array specifying the properties to traverse and enumerate. All other properties are ignored.

Examples

//
var subject = {
  string1: "Pretty",
  array1: [
    "Little Clouds",
    "Little Trees"
  ]
};

differentia.deepFreeze(subject);
// All Objects/Arrays within subject, and all it's children, are now frozen.

deepSeal

Function

deepFreeze( subject [, search = null ] );

Traverses and enumerates subject, sealing it and and it's children. Uses Object.seal(). Returns the sealed Object/Array. The method directly mutates the Object/Array.

Parameters

  • subject Object/Array

    The Object or Array to seal.

  • search (Optional) Object/Array

    An Object or Array specifying the properties to traverse and enumerate. All other properties are ignored.

Examples

var subject = {
  string1: "Pretty",
  array1: [
    "Little Clouds",
    "Little Trees"
  ]
};

differentia.deepSeal(subject);
// All Objects/Arrays within subject, and all it's children, are now sealed.

paths

Function

paths( subject [, search = null ] );

Traverses and enumerates subject, returning an array listing all paths of the tree.

Parameters

  • subject Object/Array

    The Object or Array to search.

  • search (Optional) Object/Array

    An Object or Array specifying the properties to traverse and enumerate. All other properties are ignored.

Examples

var subject = {
  string1: "Pretty",
  array1: [
    "Little Clouds",
    "Little Trees"
  ]
};

var paths = differentia.paths(subject);

console.log(paths);
/* Logs:
[
  ["searchRoot", "string1"],
  ["searchRoot", "array1", "0"],
  ["searchRoot", "array1", "1"]
]
*/

pathFind

Function

pathFind( subject, findValue [, search = null ] );

Traverses and enumerates subject, searching for findValue. Returns an Array containing the path of findValue, or null if it was not found.

Parameters

  • subject Object/Array

    The Object or Array to search.

  • findValue Object/Array

    The value to find the path of.

  • search (Optional) Object/Array

    An Object or Array specifying the properties to traverse and enumerate. All other properties are ignored.

Examples

var subject = {
  string1: "Pretty",
  array1: [
    "Little Clouds",
    "Little Trees"
  ]
};

var path = differentia.pathFind(subject, "Little Trees");

console.log(path);
/* Logs:
[
  ["searchRoot", "array1", "1"]
]
*/

diffPaths

Function

diffPaths( subject, compare [, search = null ] );

Traverses and enumerates subject, returning an array listing all paths of the tree which differ from the paths of compare.

Parameters

  • subject Object/Array

    The Object or Array to search.

  • compared Object/Array

    The Object or Array to compare to subject.

  • search (Optional) Object/Array

    An Object or Array specifying the properties to traverse and enumerate. All other properties are ignored.

Examples

var subject = {
  string1: "Pretty",
  array1: [
    "Little Clouds",
    "Little Trees"
  ]
};

var compared = {
  string2: "Pretty",
  array1: [
    "Little Branches",
    "Little Leaves"
  ]
};

var differingPaths = differentia.diffPaths(subject, compare);

console.log(differingPaths);
/* Logs:
[
  ["searchRoot","string1"],
  ["searchRoot","array1","0"],
  ["searchRoot","array1","1"]
]
*/

Higher-Order Functions

forEach

Higher-Order Function

forEach( subject , callback [, search = null ] );

A simple IOC wrapper to the dfs iterator. callback is executed for each element. Unlike Array.prototype.forEach, this implementation allows a return value of any type, which will be returned to the caller.

Parameters

  • subject Object/Array

    The root Object or Array to enumerate & traverse.

  • callback Function

    The callback function to execute for each element.

  • search (Optional) Object/Array

    An Object or Array specifying the properties to traverse and enumerate. All other properties are ignored.

Callback Parameters

  • currentValue

    The value of the element of enumeration. Equal to subject[accessor].

  • accessor

    The accessor being used to retrieve currentValue from the Object/Array being enumerated.

  • subject

    The Object/Array being enumerated.

Examples

var subject = {
  greetings1: [
    "Hello World!"
  ],
  greetings2: [
    "Good Morning!"
  ]
};

differentia.forEach(subject, function (currentValue, accessor, subject) {
  console.log(accessor);
  console.log(currentValue);
});

// Starts on the top layer of the root of subject:
// Logs "greetings1"
// Logs ["Hello World!"]
// Logs "greetings2"
// Logs ["Good Morning!"]

// Finished enumerating root Object...
// Now it will traverse and enumerate Objects/Arrays it saw:
// Logs 0
// Logs "Good Morning!"
// Logs 0
// Logs "Hello World!"

find

Higher-Order Function

find( subject , callback [, search = null ] );

A simple IOC wrapper to the dfs iterator. callback is executed for each element. If callback returns true at any time, then currentValue is immediately returned. If callback never returns true, then undefined is returned.

Parameters

  • subject Object/Array

    The root Object or Array to enumerate & traverse.

  • callback Function

    The callback function to execute for each element.

  • search (Optional) Object/Array

    An Object or Array specifying the properties to traverse and enumerate. All other properties are ignored.

Callback Parameters

  • currentValue Mixed

    The value of the element of enumeration. Equal to subject[accessor].

  • accessor Mixed

    The accessor being used to retrieve currentValue from the Object/Array being enumerated.

  • subject Object/Array

    The Object/Array being enumerated.

Examples

var subject = {
  greetings1: [
    "Hello World!"
  ],
  greetings2: [
    "Good Morning!"
  ]
};

// This will find a value.
var foundValue = differentia.find(subject, function (currentValue, accessor, subject) {
  return currentValue === "Good Morning!";
});
console.log(foundValue); // Logs "Good Morning!";

// This will not find a value.
foundValue = differentia.find(subject, function (currentValue, accessor, subject) {
  return currentValue === "This does not exist in the Array!";
});
console.log(foundValue); // Logs undefined;

some

Higher-Order Function

some( subject , callback [, search = null ] );

A simple IOC wrapper to the dfs iterator. callback is executed for each element. If callback returns true at any time, then true is immediately returned. If callback never returns true, then false is returned. You can use this function to test if a least one element of the Object tree passes a test.

Parameters

  • subject Object/Array

    The root Object or Array to enumerate & traverse.

  • callback Function

    The callback function to execute for each element.

  • search (Optional) Object/Array

    An Object or Array specifying the properties to traverse and enumerate. All other properties are ignored.

Callback Parameters

  • currentValue Mixed

    The value of the element of enumeration. Equal to subject[accessor].

  • accessor Mixed

    The accessor being used to retrieve currentValue from the Object/Array being enumerated.

  • subject Object/Array

    The Object/Array being enumerated.

Examples

var subject = [100, 200, 300, 400, 500];

// This test will pass for at least one value, and will not run more than once.
var passed = differentia.some(subject, function (currentValue, accessor, subject) {
  return currentValue === 300;
});
console.log(passed); // Logs true, at least one test passed.

// This test will fail for all values.
passed = differentia.some(subject, function (currentValue, accessor, subject) {
  return currentValue === 9000;
});
console.log(passed); // Logs false, all tests failed.

every

Higher-Order Function

every( subject , callback [, search = null ] );

A simple IOC wrapper to the dfs iterator. callback is executed for each element. If callback returns false (or a non-truthy value) at any time, then false is immediately returned. If callback returns true for every element, then true is returned. You can use this function to test if all elements of the Object tree pass a test.

Parameters

  • subject Object/Array

    The root Object or Array to enumerate & traverse.

  • callback Function

    The callback function to execute for each element.

  • search (Optional) Object/Array

    An Object or Array specifying the properties to traverse and enumerate. All other properties are ignored.

Callback Parameters

  • currentValue Mixed

    The value of the element of enumeration. Equal to subject[accessor].

  • accessor Mixed

    The accessor being used to retrieve currentValue from the Object/Array being enumerated.

  • subject Object/Array

    The Object/Array being enumerated.

Examples

var subject = [100, 200, 300, 400, 500];

// This test will pass for all values.
var passed = differentia.every(subject, function (currentValue, accessor, subject) {
  return currentValue >= 100;
});
console.log(passed); // Logs true, all tests passed.

// This test will fail for the first value, and will not run more than once.
passed = differentia.every(subject, function (currentValue, accessor, subject) {
  return currentValue === 9000;
});
console.log(passed); // Logs false, at least one test failed.

map

Higher-Order Function

map( subject , callback [, search = null ] );

A simple IOC wrapper to the dfs iterator. Constructs a structural copy of subject using the return values of callback, which is executed once for each primitive element.

Parameters

  • subject Object/Array

    The root Object or Array to enumerate & traverse.

  • callback Function

    The callback function to execute for each primitive element. Any return value (including undefined) will overwrite any primitives in the copy.

  • search (Optional) Object/Array

    An Object or Array specifying the properties to traverse and enumerate. All other properties are ignored.

Callback Parameters

  • currentValue

    The value of the element of enumeration. Equal to subject[accessor].

  • accessor

    The accessor being used to retrieve currentValue from the Object/Array being enumerated.

  • subject

    The Object/Array being enumerated.

Examples

var subject = {
  two: [2,4,6,8,10,12],
  thirteen: [13,15,17,19,21]
};

// Will increment all numbers and save them to a copy
var copy = differentia.map(subject, function (currentValue, accessor, subject) {
  if (typeof currentValue === "number") {
    return currentValue + 1;
  } else {
    return currentValue;
  }
});

console.log(copy);
// Logs:
/*
{
  two: [3,5,7,9,11,13],
  thirteen: [14,16,18,20,22]
};
*/

filter

Higher-Order Function

filter( subject , callback [, search = null ] );

A simple IOC wrapper to the bfs iterator. Constructs a structural copy of subject using only values/paths which pass the test in callback, which is executed once for each primitive element.

Parameters

  • subject Object/Array

    The root Object or Array to enumerate & traverse.

  • callback Function

    The callback function to execute for each primitive element. If callback returns true, the current value and node path will be cloned.

  • search (Optional) Object/Array

    An Object or Array specifying the properties to traverse and enumerate. All other properties are ignored.

Callback Parameters

  • currentValue

    The value of the element of enumeration. Equal to subject[accessor].

  • accessor

    The accessor being used to retrieve currentValue from the Object/Array being enumerated.

  • subject

    The Object/Array being enumerated.

Examples

var subject = {
  people: [
    {
      name: "Jon Snow",
      number: 5555555555
    },
    {
      name: "John Madden",
      number: 1231231234
    },
    {
      name: "Jimmy Neutron",
      number: 0001112222
    }
  ],
  peopleCount: 3
};

// Will clone all numbers and their paths into a new Object
var copy = differentia.filter(subject, function (currentValue, accessor, subject) {
  return typeof currentValue === "number";
});

console.log(copy);
// Logs:
/*
{
  "peopleCount": 3,
  "people": [
    {
      "number": 5555555555
    },
    {
      "number": 1231231234
    },
    {
      "number": 300178
    }
  ]
}
*/