From 66470079134a15c30d7b4e5c090ccd3ef6f17ad9 Mon Sep 17 00:00:00 2001 From: Planeshifter Date: Sun, 24 May 2015 03:15:49 -0400 Subject: [PATCH 1/5] [UPDATE] todo, accessor --- .editorconfig | 11 +++++ .gitattributes | 1 + .jshintignore | 14 ++++++ .jshintrc | 71 +++++++++++++++++++++++++++++ .npmignore | 5 ++- .travis.yml | 11 ++++- LICENSE | 4 +- Makefile | 37 +++++++++++---- README.md | 39 +++++++++++++--- examples/index.js | 4 +- lib/index.js | 112 +++++++++++++++++++++------------------------- package.json | 16 +++---- test/test.js | 68 +++++++++++++++++++++++++++- 13 files changed, 299 insertions(+), 94 deletions(-) create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 .jshintignore create mode 100644 .jshintrc diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..8e74bf3 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false \ No newline at end of file diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..176a458 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto diff --git a/.jshintignore b/.jshintignore new file mode 100644 index 0000000..3163c22 --- /dev/null +++ b/.jshintignore @@ -0,0 +1,14 @@ + +# Directories # +############### +build/ +reports/ +dist/ + +# Node.js # +########### +/node_modules/ + +# Git # +####### +.git* diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 0000000..d09f1fa --- /dev/null +++ b/.jshintrc @@ -0,0 +1,71 @@ +{ + "bitwise": false, + "camelcase": false, + "curly": true, + "eqeqeq": true, + "es3": false, + "forin": true, + "freeze": true, + "immed": true, + "indent": 4, + "latedef": "nofunc", + "newcap": true, + "noarg": true, + "noempty": false, + "nonbsp": true, + "nonew": true, + "plusplus": false, + "quotmark": "single", + "undef": true, + "unused": true, + "strict": true, + "maxparams": 10, + "maxdepth": 5, + "maxstatements": 100, + "maxcomplexity": false, + "maxlen": 1000, + "asi": false, + "boss": false, + "debug": false, + "eqnull": false, + "esnext": false, + "evil": false, + "expr": false, + "funcscope": false, + "globalstrict": false, + "iterator": false, + "lastsemic": false, + "laxbreak": false, + "laxcomma": false, + "loopfunc": false, + "maxerr": 1000, + "moz": false, + "multistr": false, + "notypeof": false, + "proto": false, + "scripturl": false, + "shadow": false, + "sub": true, + "supernew": false, + "validthis": false, + "noyield": false, + "browser": true, + "browserify": true, + "couch": false, + "devel": true, + "dojo": false, + "jasmine": false, + "jquery": false, + "mocha": true, + "mootools": false, + "node": true, + "nonstandard": false, + "prototypejs": false, + "qunit": false, + "rhino": false, + "shelljs": false, + "worker": false, + "wsh": false, + "yui": false, + "globals": {} +} \ No newline at end of file diff --git a/.npmignore b/.npmignore index 42781b3..9db298d 100644 --- a/.npmignore +++ b/.npmignore @@ -13,6 +13,7 @@ examples/ reports/ support/ test/ +benchmark/ # Node.js # ########### @@ -46,4 +47,6 @@ Desktop.ini # Utilities # ############# .jshintrc -.travis.yml \ No newline at end of file +.jshintignore +.travis.yml +.editorconfig diff --git a/.travis.yml b/.travis.yml index 7c16620..29cff27 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,12 @@ language: node_js node_js: - - "0.10" + - '0.12' + - '0.11' + - '0.10' + - '0.8' + - 'iojs' +before_install: + - npm update -g npm after_script: - - npm run coveralls \ No newline at end of file + - npm run coveralls + diff --git a/LICENSE b/LICENSE index 2fe3939..93cf2ea 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2014 Athan Reines. +Copyright (c) 2014-2015 The Compute.io Authors. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file +SOFTWARE. diff --git a/Makefile b/Makefile index e3cad30..3234fbb 100644 --- a/Makefile +++ b/Makefile @@ -5,25 +5,29 @@ # Set the node.js environment to test: NODE_ENV ?= test +# Kernel name: +KERNEL ?= $(shell uname -s) + +ifeq ($(KERNEL), Darwin) + OPEN ?= open +else + OPEN ?= xdg-open +endif # NOTES # -NOTES ?= 'TODO|FIXME' +NOTES ?= 'TODO|FIXME|WARNING|HACK|NOTE' # MOCHA # -# Specify the test framework bin locations: MOCHA ?= ./node_modules/.bin/mocha _MOCHA ?= ./node_modules/.bin/_mocha - -# Specify the mocha reporter: MOCHA_REPORTER ?= spec # ISTANBUL # -# Istanbul configuration: ISTANBUL ?= ./node_modules/.bin/istanbul ISTANBUL_OUT ?= ./reports/coverage ISTANBUL_REPORT ?= lcov @@ -31,6 +35,12 @@ ISTANBUL_LCOV_INFO_PATH ?= $(ISTANBUL_OUT)/lcov.info ISTANBUL_HTML_REPORT_PATH ?= $(ISTANBUL_OUT)/lcov-report/index.html +# JSHINT # + +JSHINT ?= ./node_modules/.bin/jshint +JSHINT_REPORTER ?= ./node_modules/jshint-stylish/stylish.js + + # FILES # @@ -81,7 +91,8 @@ test-istanbul-mocha: node_modules NODE_ENV=$(NODE_ENV) \ NODE_PATH=$(NODE_PATH_TEST) \ $(ISTANBUL) cover \ - --dir $(ISTANBUL_OUT) --report $(ISTANBUL_REPORT) \ + --dir $(ISTANBUL_OUT) \ + --report $(ISTANBUL_REPORT) \ $(_MOCHA) -- \ --reporter $(MOCHA_REPORTER) \ $(TESTS) @@ -95,9 +106,20 @@ test-istanbul-mocha: node_modules view-cov: view-istanbul-report view-istanbul-report: - open $(ISTANBUL_HTML_REPORT_PATH) + $(OPEN) $(ISTANBUL_HTML_REPORT_PATH) +# LINT # + +.PHONY: lint lint-jshint + +lint: lint-jshint + +lint-jshint: node_modules + $(JSHINT) \ + --reporter $(JSHINT_REPORTER) \ + ./ + # NODE # @@ -116,7 +138,6 @@ clean-node: # CLEAN # - .PHONY: clean clean: diff --git a/README.md b/README.md index 783ec64..1b2413b 100644 --- a/README.md +++ b/README.md @@ -16,16 +16,41 @@ For use in the browser, use [browserify](https://github.com/substack/node-browse ## Usage -To use the module, ``` javascript var mode = require( 'compute-mode' ); ``` +#### mode( arr[, accessor]) + +For non-numeric `arrays`, provide an accessor `function` for accessing `numeric` values. + +``` javascript +var arr = [ + {'x':3}, + {'x':2}, + {'x':5}, + {'x':2}, + {'x':5} +]; + +function getValue( d ) { + return d.x; +} + +var m = mode( arr, getValue ); +// returns [2,5] +``` + + +__Note__: if provided an empty `array`, the function returns `null`. + ## Examples ``` javascript +var mode = require( 'compute-mode' ); + var data = new Array( 100 ); for ( var i = 0; i < data.length; i++ ) { @@ -52,7 +77,7 @@ This method will return a sorted `array`. ### Unit -Unit tests use the [Mocha](http://visionmedia.github.io/mocha) test framework with [Chai](http://chaijs.com) assertions. To run the tests, execute the following command in the top-level application directory: +Unit tests use the [Mocha](http://mochajs.org) test framework with [Chai](http://chaijs.com) assertions. To run the tests, execute the following command in the top-level application directory: ``` bash $ make test @@ -72,19 +97,19 @@ $ make test-cov Istanbul creates a `./reports/coverage` directory. To access an HTML version of the report, ``` bash -$ open reports/coverage/lcov-report/index.html +$ make view-cov ``` +--- ## License -[MIT license](http://opensource.org/licenses/MIT). +[MIT license](http://opensource.org/licenses/MIT). ---- ## Copyright -Copyright © 2014. Athan Reines. +Copyright © 2014-2015. The Compute.io Authors. [npm-image]: http://img.shields.io/npm/v/compute-mode.svg @@ -103,4 +128,4 @@ Copyright © 2014. Athan Reines. [dev-dependencies-url]: https://david-dm.org/dev/compute-io/mode [github-issues-image]: http://img.shields.io/github/issues/compute-io/mode.svg -[github-issues-url]: https://github.com/compute-io/mode/issues \ No newline at end of file +[github-issues-url]: https://github.com/compute-io/mode/issues diff --git a/examples/index.js b/examples/index.js index d5cc856..0980f3d 100644 --- a/examples/index.js +++ b/examples/index.js @@ -1,3 +1,5 @@ +'use strict'; + var mode = require( './../lib' ); var data = new Array( 100 ); @@ -7,4 +9,4 @@ for ( var i = 0; i < data.length; i++ ) { } console.log( mode( data ) ); -// Returns [...] \ No newline at end of file +// Returns [...] diff --git a/lib/index.js b/lib/index.js index e1b1ac3..4fa215a 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,72 +1,60 @@ +'use strict'; + +// MODULES // + +var isArray = require( 'validate.io-array' ), + isFunction = require( 'validate.io-function'); + +// MODE // + /** +* FUNCTION: mode( arr[, accessor] ) +* Computes the mode of an array. * -* COMPUTE: mode -* -* -* DESCRIPTION: -* - Computes the mode of an array. -* -* -* NOTES: -* [1] -* -* -* TODO: -* [1] -* -* -* LICENSE: -* MIT -* -* Copyright (c) 2014. Athan Reines. -* -* -* AUTHOR: -* Athan Reines. kgryte@gmail.com. 2014. -* +* @param {Array} arr - array of values +* @param {Function} [accessor] - accessor function for accessing array values +* @returns {Null|Array} mode */ +function mode( arr, clbk ) { + if ( !isArray( arr ) ) { + throw new TypeError( 'mode()::invalid input argument. Must provide an array. Value: `' + arr + '`.' ); + } -(function() { - 'use strict'; - - /** - * FUNCTION: mode( arr ) - * Computes the mode of an array. - * - * @param {Array} arr - array of values - * @returns {Array} mode - */ - function mode( arr ) { - if ( !Array.isArray( arr ) ) { - throw new TypeError( 'mode()::invalid input argument. Must provide an array.' ); + if ( arguments.length > 1 ) { + if ( !isFunction( clbk ) ) { + throw new TypeError( 'mode()::invalid input argument. Accessor must be a function. Value: `' + clbk + '`.' ); } - var len = arr.length, - count = {}, - max = 0, - vals = [], - val; + } - for ( var i = 0; i < len; i++ ) { - val = arr[ i ]; - if ( !count[ val ] ) { - count[ val ] = 0; - } - count[ val ] += 1; - if ( count[ val ] === max ) { - vals.push( val ); - } else { - max = count[ val ]; - vals = [ val ]; - } - } - return vals.sort( function sort( a, b ) { - return a - b; - }); - } // end FUNCTION mode() + var len = arr.length, + count = {}, + max = 0, + vals = [], + val; + + if ( !len ) { + return null; + } + for ( var i = 0; i < len; i++ ) { + val = clbk ? clbk( arr[ i ] ) : arr[i] ; + if ( !count[ val ] ) { + count[ val ] = 0; + } + count[ val ] += 1; + if ( count[ val ] === max ) { + vals.push( val ); + } else { + max = count[ val ]; + vals = [ val ]; + } + } + return vals.sort( function sort( a, b ) { + return a - b; + }); +} // end FUNCTION mode() - // EXPORTS // - module.exports = mode; +// EXPORTS // -})(); \ No newline at end of file +module.exports = mode; diff --git a/package.json b/package.json index c9e0110..338d55b 100644 --- a/package.json +++ b/package.json @@ -33,17 +33,15 @@ "bugs": { "url": "https://github.com/compute-io/mode/issues" }, - "dependencies": {}, + "dependencies": { + "validate.io-array": "^1.0.5", + "validate.io-function": "^1.0.2" + }, "devDependencies": { - "chai": "1.x.x", - "mocha": "1.x.x", + "chai": "2.x.x", + "mocha": "2.x.x", "coveralls": "^2.11.1", "istanbul": "^0.3.0" }, - "licenses": [ - { - "type": "MIT", - "url": "http://www.opensource.org/licenses/MIT" - } - ] + "license": "MIT" } diff --git a/test/test.js b/test/test.js index e74faa6..c398393 100644 --- a/test/test.js +++ b/test/test.js @@ -1,3 +1,4 @@ +'use strict'; // MODULES // @@ -17,7 +18,6 @@ var expect = chai.expect, // TESTS // describe( 'compute-mode', function tests() { - 'use strict'; it( 'should export a function', function test() { expect( mode ).to.be.a( 'function' ); @@ -45,6 +45,29 @@ describe( 'compute-mode', function tests() { } }); + + it( 'should throw an error if provided an accessor argument which is not a function', function test() { + var values = [ + '5', + 5, + true, + undefined, + null, + NaN, + [], + {} + ]; + + for ( var i = 0; i < values.length; i++ ) { + expect( badValue( values[i] ) ).to.throw( TypeError ); + } + function badValue( value ) { + return function() { + mode( [1,2,3], value ); + }; + } + }); + it( 'should compute the mode', function test() { var data; @@ -55,4 +78,45 @@ describe( 'compute-mode', function tests() { assert.deepEqual( mode( data ), [ 2, 4 ] ); }); -}); \ No newline at end of file + it( 'should compute the mode using an accessor', function test() { + var data, expected, actual; + + data = [ + {'x':2}, + {'x':4}, + {'x':5}, + {'x':3}, + {'x':8}, + {'x':2} + ]; + + actual = mode( data, getValue ); + expected = [ 2 ]; + + assert.deepEqual( actual, expected ); + + data = [ + {'x':2}, + {'x':4}, + {'x':5}, + {'x':3}, + {'x':8}, + {'x':4}, + {'x':2} + ]; + + actual = mode( data, getValue ); + expected = [ 2, 4 ]; + + assert.deepEqual( actual, expected ); + + function getValue( d ) { + return d.x; + } + }); + + it( 'should return null if provided an empty array', function test() { + assert.isNull( mode( [] ) ); + }); + +}); From 48ee933c3d5d7d61e9767a390cbe314626ed4eeb Mon Sep 17 00:00:00 2001 From: Planeshifter Date: Sun, 24 May 2015 03:19:11 -0400 Subject: [PATCH 2/5] [UPDATE] README.md changes --- README.md | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 1b2413b..73339c2 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,17 @@ var mode = require( 'compute-mode' ); #### mode( arr[, accessor]) +Returns the mode of the values in the input `array`. + +``` javascript +var data = [ 3, 2, 5, 2, 5 ]; + +var m = mode( data ); +// returns [2, 5] +``` + +This method will return a sorted `array` in increasing order, holding all modes. + For non-numeric `arrays`, provide an accessor `function` for accessing `numeric` values. ``` javascript @@ -68,11 +79,6 @@ $ node ./examples/index.js ``` -## Notes - -This method will return a sorted `array`. - - ## Tests ### Unit From 300cc08cbe626a0dea704d4c825de1ba9298a087 Mon Sep 17 00:00:00 2001 From: Philipp Burckhardt Date: Sun, 24 May 2015 03:21:07 -0400 Subject: [PATCH 3/5] [FIX] wording --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 73339c2..3022296 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ For use in the browser, use [browserify](https://github.com/substack/node-browse var mode = require( 'compute-mode' ); ``` -#### mode( arr[, accessor]) +#### mode( arr[, accessor] ) Returns the mode of the values in the input `array`. @@ -32,7 +32,7 @@ var m = mode( data ); // returns [2, 5] ``` -This method will return a sorted `array` in increasing order, holding all modes. +The function returns a sorted `array` holding all modes in increasing order. For non-numeric `arrays`, provide an accessor `function` for accessing `numeric` values. From 9578b2ad0d1668a03fb6bd1b1e5085dbf7bdd3e3 Mon Sep 17 00:00:00 2001 From: Philipp Burckhardt Date: Sun, 24 May 2015 04:28:26 -0400 Subject: [PATCH 4/5] [FIX] suppy index to accessor --- lib/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/index.js b/lib/index.js index 4fa215a..a0c7880 100644 --- a/lib/index.js +++ b/lib/index.js @@ -37,7 +37,7 @@ function mode( arr, clbk ) { } for ( var i = 0; i < len; i++ ) { - val = clbk ? clbk( arr[ i ] ) : arr[i] ; + val = clbk ? clbk( arr[ i ], i ) : arr[i] ; if ( !count[ val ] ) { count[ val ] = 0; } From facc6aa3ad2888a5649a0b3a3cf801bf40668e88 Mon Sep 17 00:00:00 2001 From: Eetu Huisman Date: Thu, 9 Jul 2015 16:39:21 +0300 Subject: [PATCH 5/5] [FIX] Maximum value assignment The maximum should only be assigned if the count of the current value is greater than the maximum, not every time it is not the same. --- lib/index.js | 2 +- test/test.js | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/index.js b/lib/index.js index a0c7880..15b740d 100644 --- a/lib/index.js +++ b/lib/index.js @@ -44,7 +44,7 @@ function mode( arr, clbk ) { count[ val ] += 1; if ( count[ val ] === max ) { vals.push( val ); - } else { + } else if ( count[ val ] > max ) { max = count[ val ]; vals = [ val ]; } diff --git a/test/test.js b/test/test.js index c398393..b5914c8 100644 --- a/test/test.js +++ b/test/test.js @@ -76,6 +76,9 @@ describe( 'compute-mode', function tests() { data = [ 2, 4, 5, 3, 8, 4, 2 ]; assert.deepEqual( mode( data ), [ 2, 4 ] ); + + data = [ 2, 2, 4 ]; + assert.deepEqual( mode( data ), [ 2 ] ); }); it( 'should compute the mode using an accessor', function test() { @@ -110,6 +113,17 @@ describe( 'compute-mode', function tests() { assert.deepEqual( actual, expected ); + data = [ + {'x':2}, + {'x':2}, + {'x':4} + ]; + + actual = mode( data, getValue ); + expected = [ 2 ]; + + assert.deepEqual( actual, expected ); + function getValue( d ) { return d.x; }