Skip to content

Instantly share code, notes, and snippets.

@alexanderscott
Created February 27, 2014 17:48
Show Gist options
  • Save alexanderscott/9255179 to your computer and use it in GitHub Desktop.
Save alexanderscott/9255179 to your computer and use it in GitHub Desktop.
JS Object Utils
"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