Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add last #9

Open
wants to merge 13 commits into
base: myexampleusername
Choose a base branch
from
113 changes: 112 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,60 @@

// YOU KNOW WHAT TO DO //

/**
* typeOf: Returns a String representing the type of the value provided.
*
* @param {*} value Value can be anything
*
* @return {String} A String value representing the type of the value, for
* example : typeOf('hello') // => 'string'
*/
function typeOf(value) {
if(Array.isArray(value)) {
return 'array';
} else if (value === null) {
return 'null';
} else if (value instanceof Date) {
return 'date';
}
return typeof value;
}
module.exports.typeOf = typeOf;

/**
* first: Returns the first or first n elements from the provided Array.
* Provding a negative value for n will result in an empty Array. If n is
* greater than the length of the Array, the full Array will be returned.
*
* @param {Array} array The Array from which to draw the first value(s).
* @param {Number} n The number of beginning elements to be returned.
*
* @return {String} A value or an Array of the first n values.
*/
function first(array, n) {
n = n || 1;
if (n < 1 || !Array.isArray(array)) return [];
return n > 1 ? array.slice(0, n) : array[0];
}
module.exports.first = first;

/**
* last: Returns the last or last n elements from the provided Array.
* Provding a negative value for n will result in an empty Array. If n is
* greater than the length of the Array, the full Array will be returned.
*
* @param {Array} array The Array from which to draw the last value(s).
* @param {Number} n The number of ending elements to be returned.
*
* @return {String} A value or an Array of the first n values.
*/
function last(array, n) {
n = n || 1;
if (n < 1 || !Array.isArray(array)) return [];
return n > 1 ? array.slice(-n) : array[array.length - 1];
}
module.exports.last = last;

/**
* each: Designed to loop over a collection, Array or Object, and applies the action
* Function to each value in the collection.
Expand All @@ -21,4 +75,61 @@ function each(collection, action) {
}
}
}
module.exports.each = each;
module.exports.each = each;

/**
* Based a a test Function, filter is designed to collect values from a
* collection, Array or Object, and return those filtered values.
*
* @param {Array or Object} collection The collection from which to filter.
* @param {Function} test The Function that tests whether values should be
* inlcuded in the returned output. The test Function MUST return a Boolean.
*
* @return {Array} An Array of the filtered values.
*/
function filter(collection, test) {
var filtered = [];
each(collection, function(value, position, collection) {
if(test(value, position, collection)) filtered.push(value);
});
return filtered;
}
module.exports.filter = filter;

/**
* reject: Returns an Array of values from a collection, Array or Object
* that failed a test Function.
*
* @param {Array or Object} collection The collection from which to reject.
* @param {Function} test The Function that tests whether values should be
* rejected. If the test Function returns false, the value is added to the
* rejected output. The test Function MUST return a Boolean. The test Function
* is invoked with the value, the index or key, and the collection.
*
* @return {Array} An Array of the rejected values.
*/
function reject(collection, test) {
return filter(collection, function (value, position, collection) {
return !test(value, position, collection);
});
}
module.exports.reject = reject;

/**
* Takes a collection, and applies a tranformation function to each value in
* the collection, and returns an Array of the tranformations.
*
* @param {Array or Object} collection The collection from which to map.
* @param {Function} transform The transformation Function, it MUST return a
* value representing a transformation of the collection value.
*
* @return {Array} An Array of the mapped or transformed values.
*/
function map(collection, transform) {
var mapped = [];
each(collection, function(value, position, collection) {
mapped.push(transform(value, position, collection));
});
return mapped;
}
module.exports.map = map;
33 changes: 33 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"name": "lodown",
"version": "1.0.0",
"description": "My functional programming library",
"main": "index.js",
"directories": {
"test": "test"
},
"scripts": {
"test": "istanbul cover _mocha -- test/ -R spec"
},
"repository": {
"type": "git",
"url": "git+https://github.com/myexampleusername/lodown.git"
},
"keywords": [
"functional",
"programming"
],
"author": "jfraboni",
"license": "MIT",
"bugs": {
"url": "https://github.com/myexampleusername/lodown/issues"
},
"homepage": "https://github.com/myexampleusername/lodown#readme",
"devDependencies": {
"chai": "^3.4.1",
"i": "^0.3.4",
"istanbul": "^0.4.2",
"mocha": "^2.3.4",
"sinon": "^1.17.2"
}
}
55 changes: 55 additions & 0 deletions test/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,59 @@ describe('lodown', function() {
}
});
});

describe('filter', function() {
it('filter should filter Array items based on test provided', function () {
expect(lodown.filter([1, 2, 3], function(value) { return value > 2; } )).to.eql([3]);
});
it('filter should filter Object values based on test provided', function() {
expect(lodown.filter({one: 'one', two: 'two', three: 'three'}, function(value) { return value[0] === 't' })).to.eql(['two', 'three']);
});
});

describe('reject', function() {
it('should reject elements in an Array wihtout side effects', function() {
var input = ["a", 1, "b", 2, "c", 4];
expect(lodown.reject(input, function(value, position, collection){
return typeof value === "string" || position < collection.length / 2;
})).to.eql([2,4]);
expect(input).to.eql(["a", 1, "b", 2, "c", 4]);
});
});

describe('map', function() {
it('should create an Array of transformations for each value in an Array', function () {
expect(lodown.map([1, 2, 3], function(value) { return value + 1; } )).to.eql([2, 3, 4]);
});
it('should create an Array of transformations for each value in an Object', function() {
expect(lodown.map({one: 'one', two: 'two', three: 'three'}, function(value) { return value.toUpperCase(); })).to.eql(['ONE', 'TWO', 'THREE']);
});
});

describe('typeOf', function() {
it('should return a String representing the type of the value provided', function(){
expect(lodown.typeOf([])).to.equal('array');
expect(lodown.typeOf('a')).to.equal('string');
expect(lodown.typeOf(null)).to.equal('null');
expect(lodown.typeOf(new Date())).to.equal('date');
expect(lodown.typeOf(function () { })).to.equal('function');
});
});

describe('first', function() {
it('should return the first value or n values in an Array', function() {
expect(lodown.first(["a","b","c"])).to.equal("a");
expect(lodown.first(["a","b","c"], 2)).to.eql(["a","b"]);
});
it('should return empty Array if first is invoked with negative n value', function() {
expect(lodown.first(["a","b","c"], -1)).to.eql([]);
});
it('Should return the whole Array first is invoked with n value greater than the array\'s length.', function(){
expect(lodown.first(["a","b","c"], 5)).to.eql(["a","b","c"]);
});
it('Should return empty Array if the array param is not an Array.', function() {
expect(lodown.first({a:"b"}, 2)).to.eql([]);
});
});

});