filter-objects
v2.1.1
Published
Filter or match objects simply using a pattern object
Downloads
53
Maintainers
Readme
filter-objects.js
###Use a pattern object to simply filter an array of objects or match on a single object.
Features:
- Simple 'pattern object' approach eg:
filter({fido: {color: 'black'}},arrayOfPetObjs)
- Deep object property testing
- Can define filter properties & options prior to filter call for better performance
- Filter with regular expressions - on either the pattern object or targe objects
- Filter options and functions can be defined for each object property being tested
- Custom filter functions
- Variables in the pattern and target objects
Install with:
npm install filter-objects
bower install filter-objects
Examples
// find which pets have 4 paws
var fos = require('filter-objects');
var pets = [
{ name: 'fido',
paws: {color: 'gray', count: 3},
},
{ name: 'rover',
paws: {color: 'white', count: 4},
},
];
fos.filter({paws:{count: 4}}, pets);
//[{ name: 'rover', paws: {color: 'white', count: 4}];
Filter an array of objects with better performance. Calling makeFilterFn to create your filter first embeds as much as the logic as possible into the returned filter function so that it doesn't need to be performed at the time of the actual filter call.
var filter = fos.makeFilterFn(['paws.count']);
filter({paws:{count: 4}}, pets);
//[{ name: 'rover', paws: {color: 'white', count: 4}];
Filter by regular expression - on either the pattern object or target objects (the array of objects being filtered).
var options = {regExpMatch: true};
var props = ["tail.color"];
var filter = fos.makeFilterFn(props,options);
var pObj = {tail: {color: /gr.y/}};
var tObjs = [
{type: "dog", paws: {count: 4}, tail: {count: 1, color: "black"}},
{type: "rabbit", paws: {count: 3}, tail: {count: 1, color: "white"}},
{type: "cat", paws: {count: 4}, tail: {color: "gray"}},
{type: "lizard", paws: {count: 0}, tail: {color: "grey"}},];
filter(pObj, tObjs);
// [{type: "cat", paws: {count: 4}, tail: {color: "gray"}},
// {type: "lizard", paws: {count: 0}, tail: {color: "grey"}}]
// OR filter reversing the reg exp match where the reg exp is on the
// target objects and being tested against the pattern object.
var options = {regExpMatch: true, regExpReverse: true};
var props = ["tail.color"];
var filter = fos.makeFilterFn(props,options);
var pObj = {tail: {color: 'gray'}};
var tObjs = [
{type: "dog", paws: {count: 4}, tail: {count: 1, color: "black"}},
{type: "rabbit", paws: {count: 3}, tail: {count: 1, color: "white"}},
{type: "cat", paws: {count: 4}, tail: {color: "gray"}},
{type: "lizard", paws: {count: 0}, tail: {color: /gr.y/}},];
filter(pObj, tObjs);
// [{type: "cat", paws: {count: 4}, tail: {color: "gray"}},
// {type: "lizard", paws: {count: 0}, tail: {color: /gr.y/}}]
// Properties to test do not cascade to include nested object properties so
// `propsToTest=['tail'] would not have the same result. See propsToTest section.
See performance
section for performance info.
Tested on latest versions of Node 0.10, 0.12, 4, 5 and 6.
API
Match and Filter Functions
Helper functions
Options for makeFilterFn
and makeMatchFn
regExpMatch
(Plus several related reg exp options)matchIfPObjPropMissing
matchIfTObjPropMissing
- variables (
variablesInPObj
,variablesInTObj
) propMatchFn
filter(pObj, tObjs)
Returns a new array of tObjs
that match the pObj
based on default Options if called directly or the propsToTest
and options
parameters if this function was created with makeFilterFn
. Call makeFilterFn
to create this function for better performance.
Arguments
Examples
// find which pets have gray paws regardeless if 'gray' or 'grey'
var fos = require('filter-objects');
var pets = [
{ name: 'fido',
paws: {color: 'gray', count: 3},
},
{ name: 'rover',
paws: {color: 'white', count: 4},
},
];
// create the pattern object
var pObj = {paws:{color: /gr[a,e]y/}};
// select properties and options to test
var propsToTest = ['paws.color'];
var options = {regExpMatch: true};
// create the filter function
var filter = fos.makeFilterFn(propsToTest, options);
// filter
filter(pObj, pets);
// [ { name: 'fido', paws: { color: 'gray', count: 3 } } ]
makeFilterFn(propsToTest, options)
Creates and returns a filter
function that is configured to test the properties included in propsToTest
using options
to determine how properties are tested for a match between pObj
and tObjs
.
Arguments
propsToTest
options
optional Applies to each property inpropsToTest
unlessoptions
values are included for properties inpropsToTest
.options
precedence is (1)propsToTest
options
values if set (2)options
as included here as a parameter, otherwise (3)options
default values.
Examples
See filter
.
matches(pObj, tObj)
Tests pattern object against one object. Returns true
if properties identified to be tested between pObj
and tObj
match; otherwise returns false
.
Which properties are tested and if they match is determined by whether matches
is called directly or created via the makeMatchFn
.
If matches
is created via makeMatchFn
then the propsToTest
and options
parameters determine which properties are tested for match and how the properties are tested for match. Calling the resulting matches
function created via makeMatchFn
also provides better performance than calling matches
directly.
If matches
function is called directly without creating it via makeMatchFn
, every property in the pObj
object is tested for a match and all options
values are default. Options
cannot be modified if calling matches
directly.
Arguments
Examples
// test if fido's tail color is gray
var fos = require('filter-objects');
var fido ={
tail: {color: 'gray', count: 1},
body: {color: 'black'},
housetrained: true};
var pObj = {tail: {color: 'gray'}};
fos.matches(pObj, fido); //true
});
// Or, create the matches function to include option
// such as regular expression matches.
// select the properties to be tested and the options
var propsToTest = ['tail.color'];
var options = {regExpMatch:true};
// create the custom match function
var matchFn = fos.makeMatchFn(propsToTest, options);
// include the regular expression in the 'pattern object'
var pObj = {tail:{color: /gr.y/}};
// test it
matchFn(pObj, fido); // true
makeMatchFn(propsToTest, options)
Creates and returns a matches
function that is configured to test the properties included in propsToTest
and options
to determine how properties are tested for a match. This created function will run faster than calling the matches
function directly and allows for greater control, via propsToTest
and options
, of which properties are tested and how.
Arguments
propsToTest
options
- optional Applies to each property inpropsToTest
unlessoptions
values are included for properties inpropsToTest
.options
precedence is (1)propsToTest
options
values if set (2)options
as included here as a parameter, otherwise (3)options
default values.
Examples
// test if fido has a gray tail regardless if grey or gray
var fos = require('filter-objects');
var fido ={ tail: {color: 'gray', count: 1}};
// select the properties to be tested and the options
var propsToTest = ['tail.color'];
var options = {regExpMatch:true};
// create the match function
var matchFn = fos.makeMatchFn(propsToTest, options);
// include the regular expression in the 'pattern object'
var pObj = {tail:{color: /gr.y/}};
// test it
matchFn(pObj, fido); // true
});
It would give the same result to set the options
in propsToTest
var propsToTest = {'tail.color':{regExpMatch:true}};
var matchFn = fos.makeMatchFn(propsToTest); // options not included here
matchFn(pObj, fido) // true;
pObj
"pattern object". Any object that is passed into a matches
or filter
function as the first parameter. It is used to test if it matches the target object(tObj
).
var fos = require('filter-objects');
// the target object here is fido
var fido ={
paws: {color: 'grey', count: 3},
tail: {color: 'gray', count: 1},
body: {color: 'black'},
housetrained: true};
// the pattern object
var pObj = {tail: {color: 'gray'}};
fos.matches(pObj, fido); //true
tObj
"target object". Any object that is passed into a matches
or filter
(as an array) function as the second parameter. The target object or objects is/are the object(s) that is/are being tested against the pattern object to determine if it matches. See notes and example under pObj
.
propsToTest
An array or object that contains property names and their assigned options
values, if any. Property names are strings and are in dot notation if nested; eg "tail.color" to identify the property in {tail: {color: black}}
. Properties to test do not cascade to include nested object properties; see caution note at bottom of this section.
Can take one of the following forms:
an array of strings which are the property names to be tested.
options
values cannot be specified for individual properties with this form. Example:['name', 'tail.color', 'housetrained']
an array of objects, one for each property to be tested, each containing a 'name' property assigned to the property name to be tested, and option property key/values (optional). Example:
// test using default options for housetrained; tail.color using reg exp match [{name: 'housetrained'}, {name: 'tail.color', regExpMatch: true}]
an array of objects, one for each property to be tested, each with one key which is the property name and an options object as its value. Example:
// test using default options for housetrained; tail.color using reg exp match [{'housetrained': {}}, {'tail.color': {regExpMatch: true}}]
an array of combination of the above 3 (strings and objects). Example:
['housetrained', {name: 'tail.color', regExpMatch: true},{'paws':{regExpMatch: false}}]
an object with property names as keys and
options
objects as the values. Example:// test using default options for housetrained; tail.color using reg exp match {'housetrained':{}, 'tail.color': {regExpMatch: true}}
CAUTION: Every nested object property to be tested must be included in propsToTest
if they are to be tested discretely; ie, properties to be tested are not cascaded into nested objects. For example: if the target object is {name: 'fido',paws: {count: 4, color: 'black'}}
, including 'paws' in propsToTest
does not test paws.count and paws.color. It simply will test the object {count:4, color: 'black'} using the test properties you have established so if it is a regExp test and the pattern object is {paws:'.*color.*'}, it will match because the object is simply converted to a string. To test the properties in paws, include 'paws.count' and 'paws.color' specifically in propsToTest
.
options
An object used to set the option values for match and filter functions.
//options properties & their default values
var options = {
regExpMatch: false, // match on regular expression in `pObj`
regExpReverse: false, // reg exp on the *`tObj`* and tests against the pObj
regExpIgnoreCase: false, // ignore case on reg exp match (str only)
regExpAnchorStart: false, // append "^" to beg of str for reg exp (str only)
regExpAnchorEnd: false, // append "$" to end of str for reg exp (str only)
matchIfPObjPropMissing: false, // matches if `pObj` property doesn't exist
matchIfTObjPropMissing: false, // matches if `tObj` property doesn't exist
matchIfBothPropMissing: false, // match on this property if BOTH tObj & pObj are missing
variablesAllowed: false, // replace var names with var values in `pObj` props
variablesInPObj: false, // substitute variables in prop value in pattern obj
variablesInTObj: false, // substitute variables in prop value in target obj
variables: {}, // object of variables with var names as keys
variablesStartStr: '~', // beg str in pObj prop value to find the var name
variablesEndStr: null, // end str in pObj prop value to find the var name
doNotCheckInherited: false, // do not include inherited properties
propMatchFn: null // function to call instead of std match function
};
regExpMatch
Property on the options
object that if equal to true
, filter
and matches
functions will use the pObj
property value as a regular expression to test against the tObj
property. If the pattern object property value is a string, the string will be converted to a javascript regular expression.
- valid values:
true
,false
- default:
false
Example:
// test if fido has a gray tail regardless if grey or gray
var fos = require('filter-objects');
var fido ={
paws: {color: 'grey', count: 3},
tail: {color: 'gray', count: 1},
body: {color: 'black'},
housetrained: true};
// select the properties to be tested and the options
var propsToTest = ['tail.color'];
var options = {regExpMatch:true};
// include the regular expression in the 'pattern object'
var pObj = {tail:{color: /gr[a,e]y/}};
// create the match function
var matchFn = fos.makeMatchFn(propsToTest, options);
// test it
matchFn(pObj, fido); // true
regExpReverse
Property on the options
object that reverses the regular expression test so that the tObj
is a regular expression that will be tested against the pObj
property.
Like all of the regExp options, this option is only considered if regExpMatch
= true
.
var options = {regExpMatch: true, regExpReverse: true};
var props = ["tail.color"];
var filter = fos.makeFilterFn(props,options);
var pObj = {tail: {color: 'gray'}};
var tObjs = [
{type: "dog", paws: {count: 4}, tail: {count: 1, color: "black"}},
{type: "rabbit", paws: {count: 3}, tail: {count: 1, color: "white"}},
{type: "cat", paws: {count: 4}, tail: {color: "gray"}},
{type: "lizard", paws: {count: 0}, tail: {color: /gr.y/}},];
filter(pObj, tObjs);
// [{type: "cat", paws: {count: 4}, tail: {color: "gray"}},
// {type: "lizard", paws: {count: 0}, tail: {color: /gr.y/}}]
regExpIgnoreCase
Property on the options
object that if equal to true
and regExpMatch
===true
and the pObj
property value is a string, then when the pObj
value is converted from a string to a regular expression object in matches
and filter
functions, the regular expression is included with the 'i' flag to ignore case on the regular expression match. This option value is only considered where the pObj
property value is a string. If the pObj
value is a regular expression object, then the ignore case flag can be included on that object; eg "/gray/i".
- valid values:
true
,false
- default:
false
Like all of the regExp options, this option is only considered ifregExpMatch
=true
.
Example:
// test if fido has a gray tail regardless if grey or Gray
var fos = require('filter-objects');
var fido ={
paws: {color: 'grey', count: 3},
tail: {color: 'Gray', count: 1},
body: {color: 'black'},
housetrained: true};
// select the properties to be tested and the options
var propsToTest = ['tail.color'];
var options = {regExpMatch:true, regExpIgnoreCase: true};
// include the regular expression as a string in the pattern object
var pObj = {tail:{color: 'gr[a,e]y'}};
// create the match function
var matchFn = fos.makeMatchFn(propsToTest, options);
// test it
matchFn(pObj, fido); // true
// and same approach with `filter`
// regExpIgnoreCase does not apply if pObj property is a regular expression
var pObj = {tail:{color: /gr[a,e]y/}};
matchFn(pObj, fido, function(doesMatch){
console.log(doesMatch); // false
});
// use the 'i' flag on the regular expression object instead
var pObj = {tail:{color: /gr[a,e]y/i}};
matchFn(pObj, fido); // true
// and same approach with `filter`
regExpAnchorStart
Property on the options
object that if equal to true
and regExpMatch
===true
and the pObj
property value is a string, then when the pObj
value is converted from a string to a regular expression object in matches and filter functions, it includes a '^' prepended to pObj
string value. This option value is only considered where the pObj
is a string. If the pObj
property value is a regular expression object, then the ^ can be included in the regular expression; eg, /^gray/.
- valid values:
true
,false
- default:
false
This option will rarely (ever?) be needed as this can also be achieved with a pObj
value that is a string by simply including the ^ in the string (without setting regExpAnchorStart
=true).
Like all of the regExp options, this option is only considered if regExpMatch
= true
.
These 3 would yield the same result:
var pObj = {tail: {color: '^gray'}}
var options = {regExpMatch: true}
var pObj = {tail: {color: 'gray'}}
var options = {regExpMatch: true, regExpAnchorStart: true}
var pObj = {tail: {color: /^gray/}}
var options = {regExpMatch: true}
regExpAnchorEnd
Property on the options
object that if equal to true
and regExpMatch
===true
and the pObj
property value is a string, then when the pObj
value is converted from a string to a regular expression object in matches and filter functions, it includes a '$' appended to the end of the pObj
string value. This option value is only considered where the pObj
is a string. If the pObj
property value is a regular expression object, then the $ can be included in the regular expression; eg, /gray$/.
- valid values:
true
,false
- default:
false
This option will rarely (ever?) be needed as this can also be achieved with a pObj
value that is a string by simply including the $ in the string (without setting regExpAnchorEnd
=true).
Like all of the regExp options, this option is only considered if regExpMatch
= true
.
These 3 would yield the same result:
var pObj = {tail: {color: 'gray$'}}
var options = {regExpMatch: true}
var pObj = {tail: {color: 'gray'}}
var options = {regExpMatch: true, regExpAnchorEnd: true}
var pObj = {tail: {color: /gray$/}}
var options = {regExpMatch: true}
matchIfTObjPropMissing
Property on the options
object that if equal to true
, filter
and matches
functions will return true
for the given property's match test if the property being tested does not exist on tObj
.
- valid values:
true
,false
- default:
false
Example:
// find which pets have a role of guarddog and (the breed is chihuahua or
// breed is not defined)
var fos = require('filter-objects');
var pets = [
{name: 'growler',
breed: 'chihuahua',
role: 'guarddog'},
{name: 'fido',
breed: 'lab',
role: 'pet'},
{name: 'duchy',
role: 'guarddog'},
{name: 'bruiser',
breed: 'chihuahua',
role: 'cuddler'},
]
// request is the tObj
var pObj = {role:'guarddog', breed: 'chihuahua'};
// select properties to test; role with default options
var propsToTest =
{role: {}, breed: {matchIfTObjPropMissing: true}};
// create the filter function
var filter = fos.makeFilterFn(propsToTest);
// filter
filter(pObj, pets);
// [ { name: 'growler'...},{name: 'duchy'...} ]
matchIfPObjPropMissing
Property on the options
object that if equal to true
, filter
and matches
functions will return true
for the given property's match test if the property being tested does not exist on pObj
.
- valid values:
true
,false
- default:
false
Example:
// find which pets match a request with a role of guarddog and
// (the breed is chihuahua or breed is not defined)
var fos = require('filter-objects');
// pets are the `pObjs` in this case to match on their regular expressions
var pets = [
{name: 'growler',
breed: 'chihuahua',
path: /.*role=guarddog.*/},
{name: 'fido',
breed: 'lab',
path: /.*role=pet.*/},
{name: 'duchy',
path: /.*role=guarddog.*/},
{name: 'bruiser',
breed: 'chihuahua',
path: /.*role=cuddler.*/},
]
// request is the tObj
var request = {path: '/pets?role=guarddog'}
// select properties and options to test
var propsToTest =
{path: {regExpMatch: true, regExpReverse: true},
breed: {matchIfPObjPropMissing: true}};
// create the filter function
var filter = fos.makeFilterFn(propsToTest);
// filter
filter(request, pets);
// [ { name: 'growler'...},{name: 'duchy'...} ]
});
var request = {path: '/pets?role=guarddog', breed: 'chihuahua'}
// [ { name: 'growler'...} ]
matchIfBothPropMissing
Property on the options
object that if equal to true
, filter
and matches
functions will return true
for the given property's match test if the property being tested does not exist on BOTH pObj
and tObj
.
- valid values:
true
,false
- default:
false
If matchIfTObjMissing
&/or matchIfPObjMissing
is set to true
, then the match will still return true
if either the tObj or pObj property is missing, respectively, even if both are not missing.
Example:
it('should return true if properties missing in both pObj & tObj',
function() {
var options = {
matchIfBothPropMissing:true,
// matchIfTObjPropMissing: false // default is false
// matchIfPObjPropMissing: false // default is false
};
var props = ["prop1",'prop2.cat.tail'];
var pObj = {"prop1":"abc","prop2":{"cat":{"nose":"purple"}}};
var tObj = {"prop1":"abc","prop2":{"cat":{"nose":"brown"}}};
var f = fos.makeMatchFn(props,options);
f(pObj, tObj).should.equal(true);
});
it('should return false if property exists in either pObj & tObj' +
'and matchIf_ObjPropMissing is false', function() {
var options = {
matchIfBothPropMissing:true,
// matchIfTObjPropMissing: false // default is false
// matchIfPObjPropMissing: false // default is false
};
var props = ["prop1",'prop2.cat.tail'];
var pObj = {"prop1":"abc","prop2":{"cat":{"tail":"purple"}}};
var tObj = {"prop1":"abc","prop2":{"cat":{"nose":"brown"}}};
var f = fos.makeMatchFn(props,options);
f(pObj, tObj).should.equal(false);
pObj = {"prop1":"abc","prop2":{"cat":{"nose":"purple"}}};
tObj = {"prop1":"abc","prop2":{"cat":{"tail":"brown"}}};
f(pObj, tObj).should.equal(false);
});
it('should return true if property exists in either pObj & tObj' +
'and matchIf_ObjPropMissing is true', function() {
var options = {
matchIfBothPropMissing:true,
matchIfTObjPropMissing: true,
matchIfPObjPropMissing: true
};
var props = ["prop1",'prop2.cat.tail'];
var pObj = {"prop1":"abc","prop2":{"cat":{"tail":"purple"}}};
var tObj = {"prop1":"abc","prop2":{"cat":{"nose":"brown"}}};
var f = fos.makeMatchFn(props,options);
f(pObj, tObj).should.equal(true);
pObj = {"prop1":"abc","prop2":{"cat":{"nose":"purple"}}};
tObj = {"prop1":"abc","prop2":{"cat":{"tail":"brown"}}};
f(pObj, tObj).should.equal(true);
});
variables (variablesInPObj
, variablesInTObj
)
variablesInPObj
and variablesInTObj
are properties on the options
object that if equal to true
, replaces strings that are recognized as variable names in pObj
&/or tObj
property values respectively with their respective variable values from variables
. The varible names on the property values is matched based on the variablesStartStr
and variablesEndStr
.
- valid values:
true
,false
- default:
false
Example:
// match if fido has a grey tail and paws regardless if grey or gray
var fos = require('filter-objects');
var fido ={
paws: {color: 'grey', count: 3},
tail: {color: 'gray', count: 1},
body: {color: 'black'},
housetrained: true};
var options =
{regExpMatch: true,
variablesInPObj:true,
variablesStartStr:"+",
variablesEndStr: ":",
variables: {grayColor: /gr[a,e]y/i}
};
// variable name is identified between variablesStartStr(~) and variablesEndStr(#)
// and replaced with that name from variables (grayColor => /gr[a,e]y/)
var pObj = {paws:{color: '+grayColor:'}, tail:{color: '+grayColor:'}};
var propsToTest = ['paws.color','tail.color'];
var matchFn = fos.makeMatchFn(propsToTest, options);
matchFn(pObj, fido) // true;
// Or substitue variables in both pObj and tObj
var options = {variables: {youngDog: "puppy", littleCuteUn: "puppy"}};
var props =
{"prop1":
{"variablesInTObj":true,
"variablesInPObj":true,
"variablesStartStr":"/:"}};
var pObj = {"prop1":"/:littleCuteUn"};
var tObj = {"prop1":"/:youngDog"};
var f = fos.makeMatchFn(props, options);
f(pObj, tObj); //true
variables
Property on the options
object that defines the variable names and values.
See variablesInPObj
for an example.
variablesStartStr
Property on the options
object that defines a string which, if variablesInPObj
=== true
or variablesInTObj
=== true
, determines the starting position of a variable name string in a pObj
property value that will be replaced with the variable value string of the respective variable name obtained from variables
.
See variablesInPObj
for an example.
variablesEndStr
Property on the options
object that defines a string which, if variablesInPObj
=== true
or variablesInTObj
=== true
, determines the ending position of a variable name string in a pObj
property value that will be replaced with the variable value string of the respective variable name obtained from variables
.
See variables
for examples.
doNotCheckInherited
Property on the options
object that if true
will cause matches
and filter
functions to not include inherited properties for matching of pattern &/or target objects.
- valid values:
true
,false
- default:
false
Example:
var props = ["prop1"];
var o = {"prop1":"abc"};
var pObj = Object.create(o);
var tObj = {"prop1":"abc"};
// doNotCheckInherited is set to true at global level with this call so
// all inherited properties will be ignored (considered missing)
// on both tObj and pObj.
// doNotCheckInherited could also be set at the property level on
// either or both pObj and tObj like all options.
var f = fos.makeMatchFn(props, {doNotCheckInherited: true});
f(pObj, tObj); // false
// inherited properties are considered missing if doNotCheckInherited
var props = ["prop1"];
var o = {"prop1":"abc"};
var pObj = Object.create(o);
var tObj = {"prop1":"abc"};
var options = {doNotCheckInherited: true, matchIfPObjPropMissing: true}
var f = fos.makeMatchFn(props, options);
f(pObj, tObj); // true
propMatchFn
Property on the options
object that defines a function to replace the match function between pObj
and tObj
properties.
- default:
null
Function is called with 3 parameters for each property being tested:
pObjProp
- an object-literal with these 2 properties:value
: the value of thepObj
property valueexists
:true
orfalse
depending on whether the property exists onpObj
tObjProp
- an object-literal with these 2 properties:value
: the value of thetObj
property valueexists
:true
orfalse
depending on whether the property exists ontObj
Example:
// find pets with 3 or more paws
var fos = require('filter-objects');
var pets = [
{ name: 'fido',
paws: {color: 'gray', count: 3}},
{ name: 'rover',
paws: {color: 'white', count: 4}},
{ name: 'slither',
paws: {count: 0}},
];
var pObj = {paws:{count: 3}};
// propMatchFn is called for each property with the
// pattern object property value and the target object property value
var matchFn = function(pObjProp, tObjProp) {
var hasAtLeast3Paws = tObjProp.exists === true &&
pObjProp.exists === true &&
tObjProp.value >= pObjProp.value;
return hasAtLeast3Paws;
};
var propsToTest = {'paws.count': {propMatchFn: matchFn}};
var filter = fos.makeFilterFn(propsToTest);
filter(pObj, pets);
//matchedPets = {name: 'fido'..., name:'rover'...};
setOptionsOnProps(propsToTest, options)
Helper function to modify the propsToTest
object setting options on each property. setOptionsOnProps
is called by makeFilterFn
and makeMatchFn
so setOptionsOnProps
does not need to be called prior to those. setOptionsOnProps
is exposed to see the options set for each property. As noted in makeFilterFn and makeMatchFn, options
precedence is (1) propsToTest
options
values if set (2) options
as included here as a parameter, otherwise (3) options
default values.
Arguments
propsToTest
- options: Object with any of
options
properties.
Examples
var propsToTest = [
'method',
'query.filter',
{name:'query.limit', regExpMatch: false}];
var options = {regExpMatch: true};
var updatedProps = fos.setOptionsOnProps(propsToTest, options);
console.log(updatedProps);
/*
[ { name: 'method',
regExpReverse: false,
regExpIgnoreCase: false,
regExpAnchorStart: false,
regExpAnchorEnd: false,
matchIfPObjPropMissing: false,
matchIfTObjPropMissing: false,
matchIfBothPropMissing: false,
variables: {},
variablesInPObj: false,
variablesInTObj: false,
variablesStartStr: '~',
variablesEndStr: null,
propMatchFn: null,
regExpMatch: true },
{ name: 'query.filter',
regExpReverse: false,
regExpIgnoreCase: false,
regExpAnchorStart: false,
regExpAnchorEnd: false,
matchIfPObjPropMissing: false,
matchIfTObjPropMissing: false,
matchIfBothPropMissing: false,
variables: {},
variablesInPObj: false,
variablesInTObj: false,
variablesStartStr: '~',
variablesEndStr: null,
propMatchFn: null,
regExpMatch: true },
{ name: 'query.limit',
regExpMatch: false,
regExpReverse: false,
regExpIgnoreCase: false,
regExpAnchorStart: false,
regExpAnchorEnd: false,
matchIfPObjPropMissing: false,
matchIfTObjPropMissing: false,
matchIfBothPropMissing: false,
variables: {},
variablesInPObj: false,
variablesInTObj: false,
variablesStartStr: '~',
variablesEndStr: null,
propMatchFn: null } ]
*/
// Above can just be informational if needed or can be fed into makeFilterFn or makeMatchFn
var filter = makeFilterFn(updatedProps);
// which would have the same result as this:
var filter = makeFilterFn(propsToTest, options);
setNestedPropOptions(propsToTest, propOptions)
Helper function to modify propsToTest
so that options for each property cascade from higher level properties in propOptions
to lower level properties. propsToTest can then be used as input to makeFilterFn or makeMatchFn. (Note that only options are cascaded. Which properties is not cascaded. See propsToTest
).
Arguments
propsToTest
- propOptions: A literal object with propNames as keys and
options
as values.
Examples
var propsToTest = [
'method',
'query',
'query.filter',
{name:'query.limit', regExpMatch: false},
'query.filter.sort'];
var propOptions = {
'query': {regExpMatch: true}, // cascade this option to all 'query.x' where isn't set on lower levels
'query.limit': {variablesInTObj: true}
};
var updatedProps = fos.setNestedPropOptions(propsToTest, propOptions);
console.log(updatedProps);
/*
{ method: {},
query: { regExpMatch: true },
'query.filter': { regExpMatch: true },
'query.limit': { regExpMatch: false, variablesInTObj: true },
'query.filter.sort': { regExpMatch: true } }
*/
var options = {regExpReverse: true};
var filter = makeFilterFn(propsToTest, options);
// filter will test properties in propsToTest with those options
// and defaulting to regExpReverse to true across all of them
// (so for all props in propsToTest because it isn't set in any of the properties)
// Any option that isn't set in propsToTest or options will be set
// according to global options default - see options section.
...
Performance
An overall summary of benchmark performance tests can be found here. Details can be found in the performance/results folder of the perf-results branch.
Some general observations from the performance benchmark tests:
- Always use
makeFilterFn
to create your filter if possible rather than callingfilter
directly. Runningmatches
withoutmakeMatchFn
(on whichfilter
is based) can run about 10 times slower. - 95% of response times for
filter
are less than .10 μs and 10 μs per property (μs = microsecond = .001 millisecond) on a fresh build smallest available aws Linux server. This means that if filtering on one property, each filtered object responded within .10 μs and 10 μs 95% of the time. If filtering on 10 properties, it would have responded within 1 μs and 100 μs per object 95% of the time (10 x). - Depth of properties matters. This is true for both hard-coded array filters (using javascript Array.prototype.filter directly) or using filter-objects. Filtering on bojects with properties going from 1 deep to 4 deep increased the result time anywhere from 0 to almost 6 times with most response times increasing 2-3 times (again, looking at 95th percentile).
- Still call Array.prototype.filter directly if you can and if performance is paramount. filter-objects adds performance overhead to calling Array.prototype.filter directly - as would be expected. The 95th percentile response time increased from a range of .07-1.24 μs per filter property for calling Array.prototype.filter directly to a range of 1.38-4.33 μs for the same filters with filter-objects (again - using makeFilterFn).