diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..34977ee --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules +.idea \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..c73310b --- /dev/null +++ b/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - "0.12" + - "iojs" +sudo: false \ No newline at end of file diff --git a/History.md b/History.md new file mode 100644 index 0000000..da83882 --- /dev/null +++ b/History.md @@ -0,0 +1,4 @@ +0.0.0 / HEAD +============ + +* first release \ No newline at end of file diff --git a/README.md b/README.md index 5ce66d3..9cf3f55 100644 --- a/README.md +++ b/README.md @@ -1 +1,70 @@ # pad-array + +[![NPM version][npm-image]][npm-url] +[![build status][travis-image]][travis-url] +[![npm download][download-image]][download-url] + +Function to fill an array in Javascript + +This code is based in the MATLAB's code [padarray](http://www.mathworks.com/help/images/ref/padarray.html) + +## Installation + +`npm install ml-pad-array` + +## pad-array(data, [options]) + +Pads the `data` array given the current `options` (returns a new array). + +__Options__ +* padsize: Defines the number of fields that will be expanded. The default value is 1. The possible type values are: + * Number: If the value is just a number it will expand in all directions with that value. + * Array of numbers: It will expand in each direction given the values, for the array case the two values are `left and right` and for the matrix case are `left, up, right, down` +* padval: Determine how to fill the values, if the value don't match with the next strings, the new values are going to be filled with that value. The default value is 0. The special strings are: + * `'circular'`: Pad with circular repetition of elements within the dimension. + * `'replicate'`: Pad by repeating border elements of array. In this case the `padsize` shouldn't be bigger than the dimensions. + * `'symmetric'`: Pad array with mirror reflections of itself. In this case the `padsize` shouldn't be bigger than the dimensions. + +## Examples + +```js +var data = [1, 2, 3, 4]; + +// default case +var default_case = padArray(data); +default_case === [0, 1, 2, 3, 4, 0]; + +// circular case +var circular_case = padArray(data, {padsize: 5, padval: 'circular'}); +circular_case === [4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1]; + +// replicate case +var replicate_case = padArray(data, {padsize: 3, padval: 'replicate'}); +replicate_case === [1, 1, 1, 1, 2, 3, 4, 4, 4, 4]; + +// symmetric case +var symmetric_case = padArray(data, {padsize: 3, padval: 'symmetric'}); +symmetric_case === [3, 2, 1, 1, 2, 3, 4, 4, 3, 2]; +``` + +## Test + +```bash +$ npm install +$ npm test +``` + +## Authors + +- [Miguel Asencio](https://github.com/maasencioh) + +## License + +[MIT](./LICENSE) + +[npm-image]: https://img.shields.io/npm/v/ml-pad-array.svg?style=flat-square +[npm-url]: https://npmjs.org/package/ml-pad-array +[travis-image]: https://img.shields.io/travis/mljs/pad-array/master.svg?style=flat-square +[travis-url]: https://travis-ci.org/mljs/pad-array +[download-image]: https://img.shields.io/npm/dm/ml-pad-array.svg?style=flat-square +[download-url]: https://npmjs.org/package/ml-pad-array diff --git a/package.json b/package.json new file mode 100644 index 0000000..4496f6f --- /dev/null +++ b/package.json @@ -0,0 +1,37 @@ +{ + "name": "ml-pad-array", + "version": "0.0.0", + "description": "Function to fill an array in Javascript", + "main": "src/index.js", + "directories": { + "lib": "src", + "test": "test" + }, + "scripts": { + "test": "mocha --require should --reporter mocha-better-spec-reporter --recursive" + }, + "repository": { + "type": "git", + "url": "https://github.com/mljs/pad-array" + }, + "keywords": [ + "pad", + "fill", + "array", + "utils" + ], + "author": { + "name": "Miguel Asencio", + "email": "maasencioh@gmail.com" + }, + "license": "MIT", + "bugs": { + "url": "https://github.com/mljs/pad-array/issues" + }, + "homepage": "https://github.com/mljs/pad-array", + "devDependencies": { + "mocha": "latest", + "mocha-better-spec-reporter": "latest", + "should": "latest" + } +} diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..b5b7e46 --- /dev/null +++ b/src/index.js @@ -0,0 +1,112 @@ +'use strict'; + +var defaultOptions = { + padsize: 1, + padval: 0 +}; + +/** + * Case when the entry is an array + * @param data + * @param options + * @returns {Array} + */ +function arrayCase(data, options) { + var len = data.length; + if (options.padsize[0] === undefined) + options.padsize = [options.padsize, options.padsize]; + + var ans = new Array(len + options.padsize[0] + options.padsize[1]); + var cond = len + options.padsize[0] + options.padsize[1]; + var i; + + // circular option + if (options.padval === 'circular') { + for (i = 0; i < cond; i++) { + if (i < options.padsize[0]) + ans[i] = data[((len - (options.padsize[0] % len)) + i) % len]; + else if (i < (options.padsize[0] + len)) + ans[i] = data[i - options.padsize[0]]; + else + ans[i] = data[(i - options.padsize[0]) % len]; + } + } + + // replicate option + else if (options.padval === 'replicate') { + if ((options.padsize[0] > len) || (options.padsize[1] > len)) + throw new RangeError('expanded value should not be bigger than the data length'); + for (i = 0; i < cond; i++) { + if (i < options.padsize[0]) + ans[i] = data[0]; + else if (i < (options.padsize[0] + len)) + ans[i] = data[i - options.padsize[0]]; + else + ans[i] = data[len - 1]; + } + } + + // symmetric option + else if (options.padval === 'symmetric') { + if ((options.padsize[0] > len) || (options.padsize[1] > len)) + throw new RangeError('expanded value should not be bigger than the data length'); + for (i = 0; i < cond; i++) { + if (i < options.padsize[0]) + ans[i] = data[options.padsize[0] - 1 - i]; + else if (i < (options.padsize[0] + len)) + ans[i] = data[i - options.padsize[0]]; + else + ans[i] = data[2*len + options.padsize[0] - i - 1]; + } + } + + // default option + else { + for (i = 0; i < cond; i++) { + if (i < options.padsize[0]) + ans[i] = options.padval; + else if (i < (options.padsize[0] + len)) + ans[i] = data[i - options.padsize[0]]; + else + ans[i] = options.padval; + } + } + + return ans; +} + +/** + * Case when the entry is a matrix + * @param data + * @param options + * @returns {Array} + */ +function matrixCase(data, options) { + var row = data.length; + var col = data[0].length; + if (options.padsize[0] === undefined) + options.padsize = [options.padsize, options.padsize, options.padsize, options.padsize]; + throw new Error('matrix not supported yet, sorry'); +} + +/** + * Pads and array + * @param {Array } data + * @param {object} options + */ +function padArray (data, options) { + options = options || {}; + options.padsize = options.padsize || defaultOptions.padsize; + options.padval = options.padval || defaultOptions.padval; + + if (Array.isArray(data)) { + if (Array.isArray(data[0])) + return matrixCase(data, options); + else + return arrayCase(data, options); + } + else + throw new TypeError('data should be an array'); +} + +module.exports = padArray; diff --git a/test/test.js b/test/test.js new file mode 100644 index 0000000..d1ddd22 --- /dev/null +++ b/test/test.js @@ -0,0 +1,52 @@ +'use strict'; + +var padArray = require('..'); + +describe('Array test', function () { + + it('Default test', function () { + var data = [1, 2, 3, 4]; + var model = padArray(data); + model[0].should.equal(0); + }); + + it('Replicate test', function () { + var data = [1, 2, 3, 4]; + var options = { + padsize: 3, + padval: 'replicate' + }; + var model = padArray(data, options); + model[0].should.equal(1); + }); + + it('Circular test', function () { + var data = [1, 2, 3, 4]; + var options = { + padsize: 5, + padval: 'circular' + }; + var model = padArray(data, options); + model[0].should.equal(4); + }); + + it('Symmetric test', function () { + var data = [1, 2, 3, 4]; + var options = { + padsize: 3, + padval: 'symmetric' + }; + var model = padArray(data, options); + model[0].should.equal(3); + }); + + it('Numeric test', function () { + var data = [1, 2, 3, 4]; + var options = { + padsize: 3, + padval: 8 + }; + var model = padArray(data, options); + model[0].should.equal(8); + }); +}); \ No newline at end of file