/*______________ | ______ | U I Z E J A V A S C R I P T F R A M E W O R K | / / | --------------------------------------------------- | / O / | MODULE : Uize.Data.Matches Package | / / / | | / / / /| | ONLINE : http://uize.com | /____/ /__/_| | COPYRIGHT : (c)2012-2014 UIZE | /___ | LICENSE : Available under MIT License or GNU General Public License |_______________| http://uize.com/license.html */ /* Module Meta Data type: Package importance: 2 codeCompleteness: 100 docCompleteness: 5 */ /*? Introduction The =Uize.Data.Matches= module provides methods for finding matching elements in arrays or matching properties in objects. *DEVELOPERS:* `Chris van Rensburg` In a Nutshell The =Uize.Data.Matches= module provides methods for performing the following types of matching operations... - `iterating over matches` - `removing or retaining matches` - `counting matches` - `getting the keys or values for all matches` - `getting the key or value of the first match` Iterating Over Matches To make it easy to iterate over matches in a source array, object, or range, the =Uize.Data.Matches= module provides the =Uize.Data.Matches.forEach= static method. The =Uize.Data.Matches.forEach= method can be used to `iterate over matching elements of an array`, `iterate over matching properties of an object`, or `iterate over matching values of a range`. In its most basic usage, the =Uize.Data.Matches.forEach= method lets you specify a source, a matcher, and an iterator. TYPICAL USAGE .............................................................................................. Uize.Data.Matches.forEach (sourceARRAYorOBJorINT,matcherFUNCorSTRorREGEXPorBOOL,iteratorFUNC); .............................................................................................. EXAMPLE ... Uize.Data.Matches.forEach ( ); ... The =Uize.Data.Matches.forEach= method is versatile and supports a number of different usages. For more in-depth info, consult the method's [[Uize.Data.Matches.forEach][reference documentation]]. Removing or Retaining Matches The =Uize.Data.Matches= module offers methods for processing an array, object, or range, and either removing or retaining matches. The =Uize.Data.Matches.remove= method can be used to remove matches, while the =Uize.Data.Matches.retain= method can be used to retain matches. Both of these methods support... - processing a source array, object, or range (see `Specifying a Source`) - finding matches by value and/or key/index (see `Specifying a Matcher`) - removing or retaining a maximum number of matches (see `Limiting the Number of Matches`) - modifying the original source or outputting the result to a newly created or specified target (see `Specifying a Target`) Removing Matches Matches can be removed from an array, object, or number range, using the =Uize.Data.Matches.remove= method. TYPICAL USAGE ............................................................................................. var result = Uize.Data.Matches.remove (sourceARRAYorOBJorINT,matcherFUNCorSTRorREGEXPorBOOL); ............................................................................................. EXAMPLE .............................................................................. var sparseArray = []; sparseArray [1] = 'orange'; sparseArray [5] = 'peach'; sparseArray [8] = 'apple'; sparseArray [11] = 'pear'; var denseArray = Uize.Data.Matches.remove (sparseArray,'value === undefined'}; alert (denseArray.join ('|')); // alerts the text "orange|peach|apple|pear" .............................................................................. In the above example, the sparsely populated array named =sparseArray= is being created and populated with four elements. There are gaps between the assigned elements of =sparseArray=, and the elements in these gaps will all have the value =undefined=. The =Uize.Data.Matches.remove= method is being used to produce a densely populated array from the =sparseArray= by removing every element whose value is =undefined=. You'll notice that we're `matching items using a value matcher regular expression` rather than a function. This is nice and concise. The =Uize.Data.Matches.remove= method is versatile and supports a number of different usages. For more in-depth info, consult the method's [[Uize.Data.Matches.remove][reference documentation]]. Retaining Matches . EXAMPLE ... ... Counting Matches . EXAMPLE ... ... Getting the Keys or Values of All Matches documnt... EXAMPLE ... ... Getting the Key or Value of the First Match . EXAMPLE ... ... Specifying a Source . Specifying an Array Source . Specifying an Object Source . Specifying a Range Source . Specifying a Matcher . Matching Items Using a Matcher Function . Matching Items Using a Matcher Expression String . Matching Items Using a Value Matcher Regular Expression . Matching All Items . Matching No Items . Matching by Value . Matching by Key / Index . Matching by Key and Value . Limiting the Number of Matches . Specifying a Target . */ Uize.module ({ name:'Uize.Data.Matches', builder:function () { 'use strict'; var /*** Variables for Scruncher Optimization ***/ _true = true, _false = false, _undefined, _Uize = Uize, _resolveMatcher = _Uize.resolveMatcher, /*** references to static methods used internally ***/ _forEach ; /*** Utility Functions ***/ function _filter (_source,_matcher,_maxMatches,_target,_remove) { var _sourceIsNumber = typeof _source == 'number', _sourceActsLikeArray = _sourceIsNumber || _Uize.isArray (_source) ; if (_maxMatches == _undefined) _maxMatches = Infinity ; if (typeof _target != 'object') _target = _sourceIsNumber ? [] : _target === _false ? _source : _sourceActsLikeArray ? [] : {} ; var _targetIsArray = _Uize.isArray (_target), _totalRemoved = 0, _targetLength = 0 ; if (!_targetIsArray) { if (_target == _source) _source = _Uize.copy (_target) ; _Uize.emptyOut (_target); } if (_remove) { var _resolvedMatcher = _resolveMatcher (_matcher); _matcher = function (_value,_key) { var _mustRemove = _totalRemoved < _maxMatches && _resolvedMatcher (_value,_key); _mustRemove && _totalRemoved++; return !_mustRemove; }; } _forEach ( _source, _matcher, function (_value,_key) {_target [_sourceActsLikeArray ? _targetLength++ : _key] = _value}, _remove ? _undefined : _maxMatches ); if (_sourceActsLikeArray || _targetIsArray) _target.length = _targetLength ; return _target; } function _getMatchesAsArray (_source,_matcher,_maxMatches,_returnKeys) { var _result = []; _forEach ( _source, _matcher, function (_value,_key) {_result.push (_returnKeys ? _key : _value)}, _maxMatches ); return _result; } return _Uize.package ({ forEach:_forEach = function (_source,_matcher,_iterator,_maxMatches) { if (_maxMatches == _undefined) _maxMatches = Infinity ; if (_maxMatches > 0) { _matcher = _resolveMatcher (_matcher); var _totalMatches = 0; _Uize.forEach ( _source, function (_value,_key) { if (_totalMatches < _maxMatches && _matcher (_value,_key)) { _totalMatches++; _iterator (_value,_key); } }, 0, _true ); } /*? Static Methods Uize.Data.Matches.forEach Iterates over elements in the specified source array, or properties in the specified source object, or values in the specified source range, that match the specified matching criteria. DIFFERENT USAGES `Iterate Over Matching Elements of an Array` .................................................................................... Uize.Data.Matches.forEach (sourceARRAY,matcherFUNCorSTRorREGEXPorBOOL,iteratorFUNC); .................................................................................... `Iterate Over Matching Properties of an Object` .................................................................................. Uize.Data.Matches.forEach (sourceOBJ,matcherFUNCorSTRorREGEXPorBOOL,iteratorFUNC); .................................................................................. `Iterate Over Matching Values of a Range` .................................................................................. Uize.Data.Matches.forEach (sourceINT,matcherFUNCorSTRorREGEXPorBOOL,iteratorFUNC); .................................................................................. `Iterate Over up to a Maximum Number of Matches` .................................................................................. Uize.Data.Matches.forEach ( sourceARRAYorOBJorINT,matcherFUNCorSTRorREGEXPorBOOL,iteratorFUNC,maxMatchesINT ); .................................................................................. `Iterate Over All of the Items of a Source` ......................................................................................... Uize.Data.Matches.forEach (sourceARRAYorOBJorINT,true,iteratorFUNC); Uize.Data.Matches.forEach (sourceARRAYorOBJorINT,null,iteratorFUNC); Uize.Data.Matches.forEach (sourceARRAYorOBJorINT,undefined,iteratorFUNC); Uize.Data.Matches.forEach (sourceARRAYorOBJorINT,function () {return true},iteratorFUNC); Uize.Data.Matches.forEach (sourceARRAYorOBJorINT,Uize.returnTrue,iteratorFUNC); Uize.Data.Matches.forEach (sourceARRAYorOBJorINT,'true',iteratorFUNC); ......................................................................................... `Iterate Over None of the Items of a Source` .......................................................................................... Uize.Data.Matches.forEach (sourceARRAYorOBJorINT,false,iteratorFUNC); Uize.Data.Matches.forEach (sourceARRAYorOBJorINT,function () {return false},iteratorFUNC); Uize.Data.Matches.forEach (sourceARRAYorOBJorINT,Uize.returnFalse,iteratorFUNC); Uize.Data.Matches.forEach (sourceARRAYorOBJorINT,'false',iteratorFUNC); .......................................................................................... Iterate Over Matching Elements of an Array In a typical use case, this method can be used to iterate over matching elements of an array by specifying an array as the first parameter. SYNTAX .................................................................................... Uize.Data.Matches.forEach (sourceARRAY,matcherFUNCorSTRorREGEXPorBOOL,iteratorFUNC); .................................................................................... Iterate Over Matching Properties of an Object SYNTAX .................................................................................. Uize.Data.Matches.forEach (sourceOBJ,matcherFUNCorSTRorREGEXPorBOOL,iteratorFUNC); .................................................................................. Iterate Over Matching Values of a Range SYNTAX .................................................................................. Uize.Data.Matches.forEach (sourceINT,matcherFUNCorSTRorREGEXPorBOOL,iteratorFUNC); .................................................................................. Iterate Over up to a Maximum Number of Matches SYNTAX .................................................................................. Uize.Data.Matches.forEach ( sourceARRAYorOBJorINT,matcherFUNCorSTRorREGEXPorBOOL,iteratorFUNC,maxMatchesINT ); .................................................................................. Iterate Over All of the Items of a Source SYNTAX ......................................................................................... Uize.Data.Matches.forEach (sourceARRAYorOBJorINT,true,iteratorFUNC); Uize.Data.Matches.forEach (sourceARRAYorOBJorINT,null,iteratorFUNC); Uize.Data.Matches.forEach (sourceARRAYorOBJorINT,undefined,iteratorFUNC); Uize.Data.Matches.forEach (sourceARRAYorOBJorINT,function () {return true},iteratorFUNC); Uize.Data.Matches.forEach (sourceARRAYorOBJorINT,Uize.returnTrue,iteratorFUNC); Uize.Data.Matches.forEach (sourceARRAYorOBJorINT,'true',iteratorFUNC); ......................................................................................... Iterate Over None of the Items of a Source SYNTAX .......................................................................................... Uize.Data.Matches.forEach (sourceARRAYorOBJorINT,false,iteratorFUNC); Uize.Data.Matches.forEach (sourceARRAYorOBJorINT,function () {return false},iteratorFUNC); Uize.Data.Matches.forEach (sourceARRAYorOBJorINT,Uize.returnFalse,iteratorFUNC); Uize.Data.Matches.forEach (sourceARRAYorOBJorINT,'false',iteratorFUNC); .......................................................................................... */ }, remove:function (_source,_matcher,_maxMatches,_target) { return _filter (_source,_matcher,_maxMatches,_target,_true); /*? Static Methods Uize.Data.Matches.remove Removes elements in the specified source array, or properties in the specified source object, or values in the specified source range, that match the specified matching criteria. DIFFERENT USAGES `Remove All Matching Elements of an Array` .................................................................................... Uize.Data.Matches.remove (sourceARRAY,matcherFUNCorSTRorREGEXPorBOOL,iteratorFUNC); .................................................................................... `Remove All Matching Properties of an Object` .................................................................................. Uize.Data.Matches.remove (sourceOBJ,matcherFUNCorSTRorREGEXPorBOOL,iteratorFUNC); .................................................................................. `Remove All Matching Values of a Range` .................................................................................. Uize.Data.Matches.remove (sourceINT,matcherFUNCorSTRorREGEXPorBOOL,iteratorFUNC); .................................................................................. `Remove up to a Maximum Number of Matches` .................................................................................. Uize.Data.Matches.remove ( sourceARRAYorOBJorINT,matcherFUNCorSTRorREGEXPorBOOL,iteratorFUNC,maxMatchesINT ); .................................................................................. `Remove All of the Items of a Source` ......................................................................................... Uize.Data.Matches.remove (sourceARRAYorOBJorINT,true,iteratorFUNC); Uize.Data.Matches.remove (sourceARRAYorOBJorINT,null,iteratorFUNC); Uize.Data.Matches.remove (sourceARRAYorOBJorINT,undefined,iteratorFUNC); Uize.Data.Matches.remove (sourceARRAYorOBJorINT,function () {return true},iteratorFUNC); Uize.Data.Matches.remove (sourceARRAYorOBJorINT,Uize.returnTrue,iteratorFUNC); Uize.Data.Matches.remove (sourceARRAYorOBJorINT,'true',iteratorFUNC); ......................................................................................... `Remove None of the Items of a Source` .......................................................................................... Uize.Data.Matches.remove (sourceARRAYorOBJorINT,false,iteratorFUNC); Uize.Data.Matches.remove (sourceARRAYorOBJorINT,function () {return false},iteratorFUNC); Uize.Data.Matches.remove (sourceARRAYorOBJorINT,Uize.returnFalse,iteratorFUNC); Uize.Data.Matches.remove (sourceARRAYorOBJorINT,'false',iteratorFUNC); .......................................................................................... Remove All Matching Elements of an Array In a typical use case, this method can be used to remove matching elements of an array by specifying an array as the first parameter. SYNTAX .................................................................................... Uize.Data.Matches.remove (sourceARRAY,matcherFUNCorSTRorREGEXPorBOOL,iteratorFUNC); .................................................................................... Remove All Matching Properties of an Object SYNTAX .................................................................................. Uize.Data.Matches.remove (sourceOBJ,matcherFUNCorSTRorREGEXPorBOOL,iteratorFUNC); .................................................................................. Remove All Matching Values of a Range SYNTAX .................................................................................. Uize.Data.Matches.remove (sourceINT,matcherFUNCorSTRorREGEXPorBOOL,iteratorFUNC); .................................................................................. Remove up to a Maximum Number of Matches SYNTAX .................................................................................. Uize.Data.Matches.remove ( sourceARRAYorOBJorINT,matcherFUNCorSTRorREGEXPorBOOL,iteratorFUNC,maxMatchesINT ); .................................................................................. Remove All of the Items of a Source SYNTAX ......................................................................................... Uize.Data.Matches.remove (sourceARRAYorOBJorINT,true,iteratorFUNC); Uize.Data.Matches.remove (sourceARRAYorOBJorINT,null,iteratorFUNC); Uize.Data.Matches.remove (sourceARRAYorOBJorINT,undefined,iteratorFUNC); Uize.Data.Matches.remove (sourceARRAYorOBJorINT,function () {return true},iteratorFUNC); Uize.Data.Matches.remove (sourceARRAYorOBJorINT,Uize.returnTrue,iteratorFUNC); Uize.Data.Matches.remove (sourceARRAYorOBJorINT,'true',iteratorFUNC); ......................................................................................... Remove None of the Items of a Source SYNTAX .......................................................................................... Uize.Data.Matches.remove (sourceARRAYorOBJorINT,false,iteratorFUNC); Uize.Data.Matches.remove (sourceARRAYorOBJorINT,function () {return false},iteratorFUNC); Uize.Data.Matches.remove (sourceARRAYorOBJorINT,Uize.returnFalse,iteratorFUNC); Uize.Data.Matches.remove (sourceARRAYorOBJorINT,'false',iteratorFUNC); .......................................................................................... NOTES - see also the companion `Uize.Data.Matches.retain` static method */ }, retain:function (_source,_matcher,_maxMatches,_target) { return _filter (_source,_matcher,_maxMatches,_target,_false); /*? Static Methods Uize.Data.Matches.retain Retains elements in the specified source array, or properties in the specified source object, or values in the specified source range, that match the specified matching criteria. NOTES - see also the companion `Uize.Data.Matches.remove` static method */ }, count:function (_source,_matcher,_maxMatches) { var _result = 0; _forEach (_source,_matcher,function () {_result++},_maxMatches); return _result; /*? Static Methods Uize.Data.Matches.count Returns an integer, representing the number of elements in the specified source array, or properties in the specified source object, or values in the specified source range, that match the specified matching criteria. */ }, keys:function (_source,_matcher,_maxMatches) { return _getMatchesAsArray (_source,_matcher,_maxMatches,_true); /*? Static Methods Uize.Data.Matches.keys Returns the keys/indexes for elements in the specified source array, or properties in the specified source object, or values in the specified source range, that match the specified matching criteria. NOTES - see also the companion `Uize.Data.Matches.values` static method */ }, values:function (_source,_matcher,_maxMatches) { return _getMatchesAsArray (_source,_matcher,_maxMatches,_false); /*? Static Methods Uize.Data.Matches.values Returns the values for elements in the specified source array, or properties in the specified source object, or values in the specified source range, that match the specified matching criteria. NOTES - see also the companion `Uize.Data.Matches.keys` static method */ }, firstKey:function (_source,_matcher) { return _getMatchesAsArray (_source,_matcher,1,_true) [0]; /*? Static Methods Uize.Data.Matches.firstKey Returns the key/index of the first element in the specified source array, or property in the specified source object, or value in the specified source range, that matches the specified matching criteria. NOTES - see also the companion `Uize.Data.Matches.firstValue` static method */ }, firstValue:function (_source,_matcher) { return _getMatchesAsArray (_source,_matcher,1,_false) [0]; /*? Static Methods Uize.Data.Matches.firstValue Returns the value of the first element in the specified source array, or property in the specified source object, or value in the specified source range, that matches the specified matching criteria. NOTES - see also the companion `Uize.Data.Matches.firstKey` static method */ } }); } });