Skip to content

Commit

Permalink
Added unionBy
Browse files Browse the repository at this point in the history
  • Loading branch information
ascartabelli committed Feb 14, 2017
1 parent 9bee33b commit beec0c0
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 25 deletions.
39 changes: 35 additions & 4 deletions dist/lamb.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* @overview lamb - A lightweight, and docile, JavaScript library to help embracing functional programming.
* @author Andrea Scartabelli <andrea.scartabelli@gmail.com>
* @version 0.51.0-alpha.1
* @version 0.51.0-alpha.2
* @module lamb
* @license MIT
* @preserve
Expand All @@ -17,7 +17,7 @@
* @private
* @type String
*/
lamb._version = "0.51.0-alpha.1";
lamb._version = "0.51.0-alpha.2";

// alias used as a placeholder argument for partial application
var _ = lamb;
Expand Down Expand Up @@ -4123,18 +4123,48 @@
}

/**
* Returns a list of every unique element present in the given array-like objects.
* Returns a list of every unique element present in the given array-like objects.<br/>
* Uses the ["SameValueZero" comparison]{@link module:lamb.areSVZ|areSVZ}
* to test the equality of values.<br/>
* When two values are considered equal, the first occurence will be the one included
* in the result array.<br/>
* See also {@link module:lamb.unionBy|unionBy} if you need to transform the values before
* the comparison or if you have to extract them from complex ones.
* @example
* _.union([1, 2, 3, 2], [3, 4], [1, 5]) // => [1, 2, 3, 4, 5]
* _.union("abc", "bcd", "cde") // => ["a", "b", "c", "d", "e"]
*
* @memberof module:lamb
* @category Array
* @function
* @see {@link module:lamb.unionBy|unionBy}
* @param {...ArrayLike} arrayLike
* @returns {Array}
*/
var union = compose(uniquesBy(identity), flatMapWith(dropN(0)), list);
var union = unionBy(identity);

/**
* Using the provided iteratee, builds a function that will return an array of the unique elements
* in the provided array-like objects.<br/>
* Uses the ["SameValueZero" comparison]{@link module:lamb.areSVZ|areSVZ}
* to test the equality of values.<br/>
* When two values are considered equal, the first occurence will be the one included
* in the result array.<br/>
* See also {@link module:lamb.union|union} if you don't need to transform the values.
* @example
* var unionByFloor = _.unionBy(Math.floor);
*
* unionByFloor([2.8, 3.2, 1.5], [3.5, 1.2, 4]) // => [2.8, 3.2, 1.5, 4]
*
* @memberof module:lamb
* @category Array
* @see {@link module:lamb.union|union}
* @param {ListIteratorCallback} iteratee
* @returns {Function}
*/
function unionBy (iteratee) {
return compose(uniquesBy(iteratee), flatMapWith(dropN(0)), list);
}

/**
* Returns an array comprised of the unique elements of the given array-like object.<br/>
Expand Down Expand Up @@ -4269,6 +4299,7 @@
lamb.takeWhile = takeWhile;
lamb.transpose = transpose;
lamb.union = union;
lamb.unionBy = unionBy;
lamb.uniques = uniques;
lamb.uniquesBy = uniquesBy;
lamb.zip = zip;
Expand Down
4 changes: 2 additions & 2 deletions dist/lamb.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/lamb.min.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
"coveralls": "gulp coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage"
},
"tonicExample": "var _ = require('lamb');",
"version": "0.51.0-alpha.1",
"version": "0.51.0-alpha.2",
"devDependencies": {
"coveralls": "^2.11.16",
"gulp": "^3.9.1",
Expand Down
35 changes: 33 additions & 2 deletions src/array.js
Original file line number Diff line number Diff line change
Expand Up @@ -611,18 +611,48 @@ function transpose (arrayLike) {
}

/**
* Returns a list of every unique element present in the given array-like objects.
* Returns a list of every unique element present in the given array-like objects.<br/>
* Uses the ["SameValueZero" comparison]{@link module:lamb.areSVZ|areSVZ}
* to test the equality of values.<br/>
* When two values are considered equal, the first occurence will be the one included
* in the result array.<br/>
* See also {@link module:lamb.unionBy|unionBy} if you need to transform the values before
* the comparison or if you have to extract them from complex ones.
* @example
* _.union([1, 2, 3, 2], [3, 4], [1, 5]) // => [1, 2, 3, 4, 5]
* _.union("abc", "bcd", "cde") // => ["a", "b", "c", "d", "e"]
*
* @memberof module:lamb
* @category Array
* @function
* @see {@link module:lamb.unionBy|unionBy}
* @param {...ArrayLike} arrayLike
* @returns {Array}
*/
var union = compose(uniquesBy(identity), flatMapWith(dropN(0)), list);
var union = unionBy(identity);

/**
* Using the provided iteratee, builds a function that will return an array of the unique elements
* in the provided array-like objects.<br/>
* Uses the ["SameValueZero" comparison]{@link module:lamb.areSVZ|areSVZ}
* to test the equality of values.<br/>
* When two values are considered equal, the first occurence will be the one included
* in the result array.<br/>
* See also {@link module:lamb.union|union} if you don't need to transform the values.
* @example
* var unionByFloor = _.unionBy(Math.floor);
*
* unionByFloor([2.8, 3.2, 1.5], [3.5, 1.2, 4]) // => [2.8, 3.2, 1.5, 4]
*
* @memberof module:lamb
* @category Array
* @see {@link module:lamb.union|union}
* @param {ListIteratorCallback} iteratee
* @returns {Function}
*/
function unionBy (iteratee) {
return compose(uniquesBy(iteratee), flatMapWith(dropN(0)), list);
}

/**
* Returns an array comprised of the unique elements of the given array-like object.<br/>
Expand Down Expand Up @@ -757,6 +787,7 @@ lamb.takeN = takeN;
lamb.takeWhile = takeWhile;
lamb.transpose = transpose;
lamb.union = union;
lamb.unionBy = unionBy;
lamb.uniques = uniques;
lamb.uniquesBy = uniquesBy;
lamb.zip = zip;
Expand Down
75 changes: 60 additions & 15 deletions test/spec/arraySpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -996,40 +996,85 @@ describe("lamb.array", function () {
});
});

describe("union", function () {
describe("union / unionBy", function () {
var arrs = [
[1, 2, 3],
[4, 5, 1],
[5],
[6, 7, 3, 1],
[2, 8, 3],
[9, 0],
[2, [2, 3]],
[3, [2, 3]]
];
var r1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, [2, 3], [2, 3]];
var r2 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, [2, 3]];

var data = [
[{"id": "1", "name": "foo"}],
[{"id": "1", "name": "Foo"}, {"id": "2", "name": "bar"}, {"id": "3", "name": "baz"}],
[{"id": "2", "name": "Bar"}, {"id": "1", "name": "FOO"}]
];

var dataUnionById = [
{"id": "1", "name": "foo"},
{"id": "2", "name": "bar"},
{"id": "3", "name": "baz"}
];

var unionByIdentity = lamb.unionBy(lamb.identity);
var unionAsStrings = lamb.unionBy(String);
var unionById = lamb.unionBy(lamb.getKey("id"));

describe("unionBy", function () {
it("should build a function throwing an exception if the `iteratee` is not a function or if is missing", function () {
nonFunctions.forEach(function (value) {
expect(function () { lamb.unionBy(value)([1, 2, 3]); }).toThrow();
});

expect(function () { lamb.unionBy()([1, 2, 3]); }).toThrow();
});
});

it("should return a list of every unique element present in the given arrays", function () {
expect(lamb.union([])).toEqual([]);
expect(lamb.union([1, 2], [2, 3])).toEqual([1, 2, 3]);
expect(lamb.union(
[1, 2, 3],
[4, 5, 1],
[5],
[6, 7, 3, 1],
[2, 8, 3],
[9, 0],
[2, [2, 3]],
[3, [2, 3]]
)).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 0, [2, 3], [2, 3]]);
expect(lamb.union.apply(null, arrs)).toEqual(r1);

expect(unionAsStrings([])).toEqual([]);
expect(unionAsStrings([1, 2], [2, 3])).toEqual([1, 2, 3]);
expect(unionAsStrings.apply(null, arrs)).toEqual(r2);
expect(unionById.apply(null, data)).toEqual(dataUnionById);
});

it("should work with array-like objects", function () {
expect(lamb.union("abc", "bcd", "cde")).toEqual(["a", "b", "c", "d", "e"]);
expect(unionByIdentity("abc", "bcd", "cde")).toEqual(["a", "b", "c", "d", "e"]);
});

it("should return an empty array if no arguments are supplied", function () {
it("should return an empty array if it doesn't receive any array-like object", function () {
expect(lamb.union()).toEqual([]);
expect(unionAsStrings()).toEqual([]);
});

it("should always return dense arrays", function () {
expect(lamb.union([1, , 3], [3, 5], [6, 7])).toEqual([1, void 0, 3, 5, 6, 7]);
expect(lamb.union([1, , 3], [3, 5], [void 0, 7])).toEqual([1, void 0, 3, 5, 7]);

expect(unionAsStrings([1, , 3], [3, 5], [6, 7])).toEqual([1, void 0, 3, 5, 6, 7]);
expect(unionAsStrings([1, , 3], [3, 5], [void 0, 7])).toEqual([1, void 0, 3, 5, 7]);
});

it("should throw an exception if supplied with `null` or `undefined` instead of an array-like", function () {
expect(function () { lamb.union(null); }).toThrow();
expect(function () { lamb.union(void 0); }).toThrow();
expect(function () { lamb.union([1, 2], null); }).toThrow();
expect(function () { lamb.union([1, 2], void 0); }).toThrow();

expect(function () { unionAsStrings(null); }).toThrow();
expect(function () { unionAsStrings(void 0); }).toThrow();
expect(function () { unionAsStrings([1, 2], null); }).toThrow();
expect(function () { unionAsStrings([1, 2], void 0); }).toThrow();
});

it("should treat every other value as an empty array", function () {
Expand All @@ -1043,11 +1088,11 @@ describe("lamb.array", function () {
describe("uniques / uniquesBy", function () {
var data = [
{"id": "1", "name": "foo"},
{"id": "1", "name": "foo"},
{"id": "1", "name": "Foo"},
{"id": "2", "name": "bar"},
{"id": "3", "name": "baz"},
{"id": "2", "name": "bar"},
{"id": "1", "name": "foo"}
{"id": "2", "name": "Bar"},
{"id": "1", "name": "FOO"}
];

var dataUniques = [
Expand Down

0 comments on commit beec0c0

Please sign in to comment.