Created
February 27, 2014 17:48
-
-
Save alexanderscott/9255179 to your computer and use it in GitHub Desktop.
JS Object Utils
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"use strict"; | |
var _und = require('underscore'); | |
var ObjectUtils = {}; | |
/** | |
* Find and return an Object's keys which have the greatest values | |
* @param {Object} hash - values are integers or floats | |
* @returns {Array} - array of strings (keys) | |
*/ | |
ObjectUtils.keysWithMaxValues = function(hash){ | |
var valsArr = _und.values(hash); | |
var maxVal = _und.max( valsArr ); | |
return _und.reduce(hash, function(memo, val, key){ | |
if(val === maxVal) memo.push(key); | |
return memo; | |
}, []); | |
}; | |
// Get deep value | |
// _.deep(obj, 'a.b.c.d[2]'); // 'g' | |
// | |
// Set deep value | |
// _.deep(obj, 'a.b.c.d[2]', 'george'); | |
// | |
// _.deep(obj, 'a.b.c.d[2]'); // 'george' | |
ObjectUtils.deep = function(obj, key, value){ | |
var keys = key.replace(/\[(["']?)([^\1]+?)\1?\]/g, '.$2').replace(/^\./, '').split('.'), | |
root, | |
i = 0, | |
n = keys.length; | |
// Set deep value | |
if (arguments.length > 2) { | |
root = obj; | |
n--; | |
while (i < n) { | |
key = keys[i++]; | |
obj = obj[key] = _und.isObject(obj[key]) ? obj[key] : {}; | |
} | |
obj[keys[i]] = value; | |
value = root; | |
// Get deep value | |
} else { | |
while ((obj = obj[keys[i++]]) != null && i < n) {}; | |
value = i < n ? void 0 : obj; | |
} | |
return value; | |
}; | |
// _.pluckDeep(arr, 'deeply.nested'); // ['foo', 'bar'] | |
ObjectUtils.pluckDeep = function(obj, key){ | |
return _und.map(obj, function (value) { return _und.deep(value, key); }); | |
}; | |
ObjectUtils.unpick = function(obj){ | |
// Return a copy of an object containing all but the blacklisted properties. | |
obj || (obj = {}); | |
return _und.pick(obj, _und.difference(_und.keys(obj), _und.flatten(Array.prototype.slice.call(arguments, 1)))); | |
}; | |
// Return sum of the elements | |
ObjectUtils.sum = function(obj, iterator, context) { | |
if (!iterator && _und.isEmpty(obj)) return 0; | |
var result = 0; | |
if (!iterator && _und.isArray(obj)){ | |
for(var i=obj.length-1;i>-1;i-=1){ | |
result += obj[i]; | |
} | |
return result; | |
} | |
_und.each(obj, function(value, index, list) { | |
var computed = iterator ? iterator.call(context, value, index, list) : value; | |
result += computed; | |
}); | |
return result; | |
}; | |
// Return aritmethic mean of the elements | |
// if an iterator function is given, it is applied before | |
ObjectUtils.mean = function(obj, iterator, context) { | |
if (!iterator && _und.isEmpty(obj)) return Infinity; | |
if (!iterator && _und.isArray(obj)) return _und.sum(obj)/obj.length; | |
if (_und.isArray(obj) && !_und.isEmpty(obj)) return _und.sum(obj, iterator, context)/obj.length; | |
}; | |
// Return median of the elements | |
// if the object element number is odd the median is the | |
// object in the "middle" of a sorted array | |
// in case of an even number, the arithmetic mean of the two elements | |
// in the middle (in case of characters or strings: obj[n/2-1] ) is returned. | |
// if an iterator function is provided, it is applied before | |
ObjectUtils.median = function(obj, iterator, context) { | |
if (_und.isEmpty(obj)) return Infinity; | |
var tmpObj = []; | |
if (!iterator && _und.isArray(obj)){ | |
tmpObj = _.clone(obj); | |
tmpObj.sort(function(f,s){return f-s;}); | |
} else { | |
_und.isArray(obj) && _und.each(obj, function(value, index, list) { | |
tmpObj.push(iterator ? iterator.call(context, value, index, list) : value); | |
tmpObj.sort(); | |
}); | |
} | |
return tmpObj.length%2 ? tmpObj[Math.floor(tmpObj.length/2)] : (_und.isNumber(tmpObj[tmpObj.length/2-1]) && _und.isNumber(tmpObj[tmpObj.length/2])) ? (tmpObj[tmpObj.length/2-1]+tmpObj[tmpObj.length/2]) /2 : tmpObj[tmpObj.length/2-1]; | |
}; | |
// Generate an integer Array containing an arithmetic progression. A port of | |
// the native Python `range()` function. See | |
// [the Python documentation](http://docs.python.org/library/functions.html#range). | |
// replacement of old _.range() faster + incl. convenience operations: | |
// _.nrange(start, stop) will automatically set step to +1/-1 | |
// _.nrange(+/- stop) will automatically start = 0 and set step to +1/-1 | |
ObjectUtils.nrange = function(start, stop, step) { | |
if (arguments.length <= 1) { | |
if (start === 0) | |
return []; | |
stop = start || 0; | |
start = 0; | |
} | |
step = arguments[2] || 1*(start < stop) || -1; | |
var len = Math.max(Math.ceil((stop - start) / step), 0); | |
var idx = 0; | |
var range = new Array(len); | |
do { | |
range[idx] = start; | |
start += step; | |
} while((idx += 1) < len); | |
return range; | |
}; | |
module.exports = ObjectUtils; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment