underscore.js So what exactly does Underscore do? "Underscore is a utility-belt library for JavaScript that provides a lot of the functional programming support that you would expect in Prototype.js (or Ruby), but without extending any of the built-in JavaScript objects. One of the nicer things about working in Python or Ruby are the fancy constructs like map that make life a lot easier. The current version of JavaScript, sadly, is fairly barebones when it comes to low level utilities." Array Functions compact _.compact(array) Trim out all falsy values from an array. _.compact = function(array) { return _.filter(array, _.identity); }; Returns a copy of the array with all falsy values removed. In JavaScript, false, null, 0, "", undefined and NaN are all falsy. _.compact([0, 1, false, 2, '', 3]); >> [1, 2, 3] difference _.difference(array, *others) Take the difference between one array and a number of other arrays. Only the elements present in just the first array will remain. _.difference = function(array) { var rest = flatten(arguments, true, true, 1); return _.filter(array, function(value){ return !_.contains(rest, value); }); }; Similar to without, but returns the values from array that are not present in the other arrays. _.difference([1, 2, 3, 4, 5], [5, 2, 10]); >> [1, 3, 4] findIndex _.findIndex(array, predicate, [context]) Returns the first index on an array-like that passes a predicate test _.findIndex = createPredicateIndexFinder(1); Similar to _.indexOf, returns the first index where the predicate truth test passes; otherwise returns -1. _.findIndex([4, 6, 8, 12], isPrime); >> -1 // not found _.findIndex([4, 6, 7, 12], isPrime); >> 2 first _.first(array, [n]) Aliases: head, take Get the first element of an array. Passing n will return the first N values in the array. Aliased as head and take. The guard check allows it to work with _.map. _.first = _.head = _.take = function(array, n, guard) { if (array == null) return void 0; if (n == null || guard) return array[0]; return _.initial(array, array.length - n); }; Returns the first element of an array. Passing n will return the first n elements of the array. _.first([5, 4, 3, 2, 1]); >> 5 intersection _.intersection(*arrays) Produce an array that contains every item shared between all the passed-in arrays. _.intersection = function(array) { var result = []; var argsLength = arguments.length; for (var i = 0, length = getLength(array); i < length; i++) { var item = array[i]; if (_.contains(result, item)) continue; for (var j = 1; j < argsLength; j++) { if (!_.contains(arguments[j], item)) break; } if (j === argsLength) result.push(item); } return result; }; Computes the list of values that are the intersection of all the arrays. Each value in the result is present in each of the arrays. _.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]); >> [1, 2] indexOf _.indexOf(array, value, [isSorted]) Return the position of the first occurrence of an item in an array, or -1 if the item is not included in the array. If the array is large and already in sort order, pass true for isSorted to use binary search. _.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex); Returns the index at which value can be found in the array, or -1 if value is not present in the array. If you're working with a large array, and you know that the array is already sorted, pass true for isSorted to use a faster binary search ... or, pass a number as the third argument in order to look for the first matching value in the array after the given index. _.indexOf([1, 2, 3], 2); >> 1 last _.last(array, [n]) Get the last element of an array. Passing n will return the last N values in the array. _.last = function(array, n, guard) { if (array == null) return void 0; if (n == null || guard) return array[array.length - 1]; return _.rest(array, Math.max(0, array.length - n)); }; Returns the last element of an array. Passing n will return the last n elements of the array. _.last([5, 4, 3, 2, 1]); >> 1 object _.object(list, [values]) Converts lists into objects. Pass either a single array of [key, value] pairs, or two parallel arrays of the same length — one of keys, and one of the corresponding values. _.object = function(list, values) { var result = {}; for (var i = 0, length = getLength(list); i < length; i++) { if (values) { result[list[i]] = values[i]; } else { result[list[i][0]] = list[i][1]; } } return result; }; Converts arrays into objects. Pass either a single list of [key, value] pairs, or a list of keys, and a list of values. If duplicate keys exist, the last value wins. _.object(['moe', 'larry', 'curly'], [30, 40, 50]); >> {moe: 30, larry: 40, curly: 50} _.object([['moe', 30], ['larry', 40], ['curly', 50]]); >> {moe: 30, larry: 40, curly: 50} range _.range([start], stop, [step]) Generate an integer Array containing an arithmetic progression. A port of the native Python range() function. See the Python documentation. _.range = function(start, stop, step) { if (stop == null) { stop = start || 0; start = 0; } step = step || 1; var length = Math.max(Math.ceil((stop - start) / step), 0); var range = Array(length); for (var idx = 0; idx < length; idx++, start += step) { range[idx] = start; } return range; }; A function to create flexibly-numbered lists of integers, handy for each and map loops. start, if omitted, defaults to 0; step defaults to 1. Returns a list of integers from start (inclusive) to stop (exclusive), incremented (or decremented) by step, exclusive. Note that ranges that stop before they start are considered to be zero-length instead of negative — if you'd like a negative range, use a negative step. _.range(10); >> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] _.range(1, 11); >> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] _.range(0, 30, 5); >> [0, 5, 10, 15, 20, 25] _.range(0, -10, -1); >> [0, -1, -2, -3, -4, -5, -6, -7, -8, -9] _.range(0); >> [] sortedIndex _.sortedIndex(list, value, [iteratee], [context]) Use a comparator function to figure out the smallest index at which an object should be inserted so as to maintain order. Uses binary search. _.sortedIndex = function(array, obj, iteratee, context) { iteratee = cb(iteratee, context, 1); var value = iteratee(obj); var low = 0, high = getLength(array); while (low < high) { var mid = Math.floor((low + high) / 2); if (iteratee(array[mid]) < value) low = mid + 1; else high = mid; } return low; }; Uses a binary search to determine the index at which the value should be inserted into the list in order to maintain the list's sorted order. If an iteratee function is provided, it will be used to compute the sort ranking of each value, including the value you pass. The iteratee may also be the string name of the property to sort by (eg. length). _.sortedIndex([10, 20, 30, 40, 50], 35); >> 3 var stooges = [{name: 'moe', age: 40}, {name: 'curly', age: 60}]; _.sortedIndex(stooges, {name: 'larry', age: 50}, 'age'); >> 1 uniq _.uniq(array, [isSorted], [iteratee]) Alias: unique Produce a duplicate-free version of the array. If the array has already been sorted, you have the option of using a faster algorithm. Aliased as unique. _.uniq = _.unique = function(array, isSorted, iteratee, context) { if (!_.isBoolean(isSorted)) { context = iteratee; iteratee = isSorted; isSorted = false; } if (iteratee != null) iteratee = cb(iteratee, context); var result = []; var seen = []; for (var i = 0, length = getLength(array); i < length; i++) { var value = array[i], computed = iteratee ? iteratee(value, i, array) : value; if (isSorted) { if (!i || seen !== computed) result.push(value); seen = computed; } else if (iteratee) { if (!_.contains(seen, computed)) { seen.push(computed); result.push(value); } } else if (!_.contains(result, value)) { result.push(value); } } return result; }; Produces a duplicate-free version of the array, using === to test object equality. In particular only the first occurence of each value is kept. If you know in advance that the array is sorted, passing true for isSorted will run a much faster algorithm. If you want to compute unique items based on a transformation, pass an iteratee function. _.uniq([1, 2, 1, 4, 1, 3]); >> [1, 2, 4, 3] union _.union(*arrays) Produce an array that contains the union: each distinct element from all of the passed-in arrays. _.union = function() { return _.uniq(flatten(arguments, true, true)); }; Computes the union of the passed-in arrays: the list of unique items, in order, that are present in one or more of the arrays. _.union([1, 2, 3], [101, 2, 1, 10], [2, 1]); >> [1, 2, 3, 101, 10] unzip _.unzip(array) Complement of _.zip. Unzip accepts an array of arrays and groups each array’s elements on shared indices _.unzip = function(array) { var length = array && _.max(array, getLength).length || 0; var result = Array(length); for (var index = 0; index < length; index++) { result[index] = _.pluck(array, index); } return result; }; The opposite of zip. Given an array of arrays, returns a series of new arrays, the first of which contains all of the first elements in the input arrays, the second of which contains all of the second elements, and so on. _.unzip([["moe", 30, true], ["larry", 40, false], ["curly", 50, false]]); >> [['moe', 'larry', 'curly'], [30, 40, 50], [true, false, false]] without _.without(array, *values) Return a version of the array that does not contain the specified value(s). _.without = function(array) { return _.difference(array, slice.call(arguments, 1)); }; Returns a copy of the array with all instances of the values removed. _.without([1, 2, 1, 0, 3, 1, 4], 0, 1); >> [2, 3, 4] zip _.zip(*arrays) Zip together multiple lists into a single array — elements that share an index go together. _.zip = function() { return _.unzip(arguments); }; Merges together the values of each of the arrays with the values at the corresponding position. Useful when you have separate data sources that are coordinated through matching array indexes. Use with apply to pass in an array of arrays. If you're working with a matrix of nested arrays, this can be used to transpose the matrix. _.zip(['moe', 'larry', 'curly'], [30, 40, 50], [true, false, false]); >> [["moe", 30, true], ["larry", 40, false], ["curly", 50, false]]