public
Last active

My extensions for underscore.js

  • Download Gist
underscore_extensions.js
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
_.mixin({
/* Like extend but get key/values object->key_names */
extend_from: function(object, source_object, key_names) {
return _(object).extend(_(source_object).slice(key_names));
},
/* Return a new object with the merged properties of all objects in arguments */
merge: function() {
var objects = arguments;
return _.reduce(_.rest(objects), function(obj, o) {
return _.extend(obj, o);
}, _.clone(_.first(objects) || {}));
},
 
/* Build an object with [key, value] from pair list or callback */
mash: function(list, callback, context) {
var pair_callback = callback || _.identity;
return _.reduce(list, function(obj, value, index, list) {
var pair = pair_callback.call(context, value, index, list);
if (typeof pair == "object" && pair.length == 2) {
obj[pair[0]] = pair[1];
}
return obj;
}, {});
},
 
/* Return pairs [key, value] of object */
pairs: function(object) {
return _.map(object, function(value, key) {
return [key, value];
});
},
 
/* take elements from list while callback condition is met */
takeWhile: function(list, callback, context) {
var xs = [];
_.any(list, function(item, index, list) {
var res = callback.call(context, item, index, list);
if (res) {
xs.push(item);
return false;
} else {
return true;
}
});
return xs;
},
 
/* Repeat item n times */
repeat: function(item, n) {
var output = [];
for(var i=0; i < n; i++) {
output.push(item);
}
return output;
},
 
/* Return true if array_of_objects contain an object (deep comparison) */
containsObject: function(array_of_objects, obj) {
return _(array_of_objects).any(function(o) { return _(o).isEqual(obj) });
},
 
/* Return the first true element returned by the callback block (map + first) */
mapDetect: function(list, callback, context) {
var output;
_.any(list, function(item, index, list) {
var res = callback.call(context, item, index, list);
if (res) {
output = res;
return true;
} else {
return false;
}
});
return output;
},
/* Return copy of object containing only given keys */
slice: function(object, keys) {
return _.reduce(_(object).keys(), function(obj, key) {
if (_.include(keys, key))
obj[key] = object[key];
return obj;
}, {});
},
 
/* Like _.uniq but using a custom comparison function */
uniqWith: function(list, compare_function, context) {
var output = [];
_.each(list, function(item) {
if (!_.any(output, function(x) { return compare_function.call(context, item, x); })) {
output.push(item);
}
});
return output;
},
 
/* Return a one-level flattened version of an array. */
flatten1: function(array) {
return _.reduce(array, function(memo, value) {
return memo.concat(value);
}, []);
},
 
/* Return true if object is not empty */
isNotEmpty: function(obj) {
return !_.isEmpty(obj);
},
 
/* Inspect object and print it to the JS console */
inspect: function(obj) {
console.log(JSON.stringify(obj, null));
}
})

I've added support for providing an optional context argument, and invoking the callback function with the typical value, index, list parameters common to other Underscore functions.

_.mixin({
  mash: function(list, callback, context) {
    callback || (callback = _.identity);
    return _.reduce(list, function(obj, value, index, list) {
      var pair = callback.call(context, value, index, list);
      if (typeof pair == "object" && pair.length == 2) {
        obj[pair[0]] = pair[1];
      }
      return obj;
    }, {});
  }
});

@kitcambridge: nice! maybe it should check pair.length == 2?

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.