From 0ec859a142d2eb255b561c18f9d2598c589d95e6 Mon Sep 17 00:00:00 2001 From: Jeremy Ashkenas Date: Tue, 12 Jul 2011 16:48:30 -0400 Subject: [PATCH] Issue #225, adding _.union, _.difference, to complement _.without and _.intersection. --- test/arrays.js | 18 ++++++++++++++---- underscore.js | 19 +++++++++++++++---- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/test/arrays.js b/test/arrays.js index e031afe9b..32dd73a55 100644 --- a/test/arrays.js +++ b/test/arrays.js @@ -65,14 +65,24 @@ $(document).ready(function() { equals(result.join(', '), '1, 2, 3, 4', 'works on an arguments object'); }); - test("arrays: intersect", function() { + test("arrays: intersection", function() { var stooges = ['moe', 'curly', 'larry'], leaders = ['moe', 'groucho']; - equals(_.intersect(stooges, leaders).join(''), 'moe', 'can take the set intersection of two arrays'); - equals(_(stooges).intersect(leaders).join(''), 'moe', 'can perform an OO-style intersection'); - var result = (function(){ return _.intersect(arguments, leaders); })('moe', 'curly', 'larry'); + equals(_.intersection(stooges, leaders).join(''), 'moe', 'can take the set intersection of two arrays'); + equals(_(stooges).intersection(leaders).join(''), 'moe', 'can perform an OO-style intersection'); + var result = (function(){ return _.intersection(arguments, leaders); })('moe', 'curly', 'larry'); equals(result.join(''), 'moe', 'works on an arguments object'); }); + test("arrays: union", function() { + var result = _.union([1, 2, 3], [2, 30, 1], [1, 40]); + equals(result.join(' '), '1 2 3 30 40', 'takes the union of a list of arrays'); + }); + + test("arrays: difference", function() { + var result = _.difference([1, 2, 3], [2, 30, 40]); + equals(result.join(' '), '1 3', 'takes the difference of two arrays'); + }); + test('arrays: zip', function() { var names = ['moe', 'larry', 'curly'], ages = [30, 40, 50], leaders = [true]; var stooges = _.zip(names, ages, leaders); diff --git a/underscore.js b/underscore.js index 66e71fc3f..0ac287e8e 100644 --- a/underscore.js +++ b/underscore.js @@ -327,8 +327,7 @@ // Return a version of the array that does not contain the specified value(s). _.without = function(array) { - var values = slice.call(arguments, 1); - return _.filter(array, function(value){ return !_.include(values, value); }); + return _.difference(array, slice.call(arguments, 1)); }; // Produce a duplicate-free version of the array. If the array has already @@ -341,9 +340,15 @@ }, []); }; + // Produce an array that contains the union: each distinct element from all of + // the passed-in arrays. + _.union = function() { + return _.uniq(_.flatten(arguments)); + }; + // Produce an array that contains every item shared between all the - // passed-in arrays. - _.intersect = function(array) { + // passed-in arrays. (Aliased as "intersect" for back-compat.) + _.intersection = _.intersect = function(array) { var rest = slice.call(arguments, 1); return _.filter(_.uniq(array), function(item) { return _.every(rest, function(other) { @@ -352,6 +357,12 @@ }); }; + // Take the difference between one array and another. + // Only the elements present in just the first array will remain. + _.difference = function(array, other) { + return _.filter(array, function(value){ return !_.include(other, value); }); + }; + // Zip together multiple lists into a single array -- elements that share // an index go together. _.zip = function() {