diff --git a/.travis.yml b/.travis.yml index deebb36..bc432e9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,3 +12,4 @@ script: after_script: - 'npm i codecov && codecov' - 'node benchmark/map.js' + - 'node benchmark/array_splice.js' diff --git a/benchmark/array_splice.js b/benchmark/array_splice.js new file mode 100644 index 0000000..8f135f7 --- /dev/null +++ b/benchmark/array_splice.js @@ -0,0 +1,148 @@ +/** + * Copyright(c) node-modules and other contributors. + * MIT Licensed + * + * Authors: + * fengmk2 (http://fengmk2.com) + */ + +'use strict'; + +/** + * Module dependencies. + */ + +var crypto = require('crypto'); +var utility = require('../'); + +var Benchmark = require('benchmark'); +var benchmarks = require('beautify-benchmark'); +var suite = new Benchmark.Suite(); + +function arraySplice(array, index) { + array.splice(index, 1); + return array; +} + +function spliceOne(array, index) { + for (var i = index, k = i + 1, n = array.length; k < n; i += 1, k += 1) { + array[i] = array[k]; + } + array.pop(); + return array; +} + +class SubArray extends Array { + spliceOne(index) { + for (let i = index, k = i + 1, n = this.length; k < n; i += 1, k += 1) { + this[i] = this[k]; + } + this.pop(); + return this; + } +} + +console.log('arraySplice([1, 2, 3], 1): %j', arraySplice([1, 2, 3], 1)); +console.log('new SubArray(1, 2, 3).spliceOne(1): %j', new SubArray(1, 2, 3).spliceOne(1)); +console.log('spliceOne([1, 2, 3], 1): %j', spliceOne([1, 2, 3], 1)); +console.log('arraySplice([1, 2, 3, 4, 5, 6, 7, 8, 9], 6): %j', + arraySplice([1, 2, 3, 4, 5, 6, 7, 8, 9], 6)); +console.log('new SubArray(1, 2, 3, 4, 5, 6, 7, 8, 9).spliceOne(6): %j', + new SubArray(1, 2, 3, 4, 5, 6, 7, 8, 9).spliceOne(6)); +console.log('spliceOne([1, 2, 3, 4, 5, 6, 7, 8, 9], 6): %j', + spliceOne([1, 2, 3, 4, 5, 6, 7, 8, 9], 6)); + +suite + +.add('arraySplice([1, 2, 3], 1)', function() { + arraySplice([1, 2, 3], 1); +}) +.add('new SubArray(1, 2, 3).spliceOne(1)', function() { + new SubArray(1, 2, 3).spliceOne(1); +}) +.add('spliceOne([1, 2, 3], 1)', function() { + spliceOne([1, 2, 3], 1); +}) + +.add('arraySplice([1, 2, 3, 4, 5, 6, 7, 8, 9], 6)', function() { + arraySplice([1, 2, 3, 4, 5, 6, 7, 8, 9], 6); +}) +.add('new SubArray(1, 2, 3, 4, 5, 6, 7, 8, 9).spliceOne(6)', function() { + new SubArray(1, 2, 3, 4, 5, 6, 7, 8, 9).spliceOne(6); +}) +.add('spliceOne([1, 2, 3, 4, 5, 6, 7, 8, 9], 6)', function() { + spliceOne([1, 2, 3, 4, 5, 6, 7, 8, 9], 6); +}) + +.add('arraySplice(new Array(20), 11)', function() { + arraySplice(new Array(20), 11); +}) +.add('new SubArray(new Array(20)).spliceOne(11)', function() { + new SubArray(new Array(20)).spliceOne(11); +}) +.add('spliceOne(new Array(20), 11)', function() { + spliceOne(new Array(20), 11); +}) + +.add('arraySplice(new Array(50), 30)', function() { + arraySplice(new Array(50), 30); +}) +.add('new SubArray(new Array(50)).spliceOne(30)', function() { + new SubArray(new Array(50)).spliceOne(30); +}) +.add('spliceOne(new Array(50), 30)', function() { + spliceOne(new Array(50), 30); +}) + +.add('arraySplice(new Array(100), 80)', function() { + arraySplice(new Array(100), 80); +}) +.add('new SubArray(new Array(100)).spliceOne(80)', function() { + new SubArray(new Array(100)).spliceOne(80); +}) +.add('spliceOne(new Array(100), 80)', function() { + spliceOne(new Array(100), 80); +}) + + +.on('cycle', function(event) { + benchmarks.add(event.target); +}) +.on('start', function(event) { + console.log('\n map Benchmark\n node version: %s, date: %s\n Starting...', + process.version, Date()); +}) +.on('complete', function done() { + benchmarks.log(); +}) +.run({ 'async': false }); + +// node benchmark/array_splice.js +// +// arraySplice([1, 2, 3], 1): [1,3] +// new SubArray(1, 2, 3).spliceOne(1): [1,3] +// spliceOne([1, 2, 3], 1): [1,3] +// arraySplice([1, 2, 3, 4, 5, 6, 7, 8, 9], 6): [1,2,3,4,5,6,8,9] +// new SubArray(1, 2, 3, 4, 5, 6, 7, 8, 9).spliceOne(6): [1,2,3,4,5,6,8,9] +// spliceOne([1, 2, 3, 4, 5, 6, 7, 8, 9], 6): [1,2,3,4,5,6,8,9] +// +// map Benchmark +// node version: v6.1.0, date: Sun May 08 2016 23:02:25 GMT+0800 (CST) +// Starting... +// 15 tests completed. +// +// arraySplice([1, 2, 3], 1) x 3,391,759 ops/sec ±1.75% (77 runs sampled) +// new SubArray(1, 2, 3).spliceOne(1) x 2,146,665 ops/sec ±2.44% (78 runs sampled) +// spliceOne([1, 2, 3], 1) x 30,957,606 ops/sec ±2.30% (76 runs sampled) +// arraySplice([1, 2, 3, 4, 5, 6, 7, 8, 9], 6) x 3,393,631 ops/sec ±1.58% (81 runs sampled) +// new SubArray(1, 2, 3, 4, 5, 6, 7, 8, 9).spliceOne(6) x 1,898,975 ops/sec ±1.36% (81 runs sampled) +// spliceOne([1, 2, 3, 4, 5, 6, 7, 8, 9], 6) x 23,286,263 ops/sec ±2.40% (72 runs sampled) +// arraySplice(new Array(20), 11) x 3,424,955 ops/sec ±1.39% (79 runs sampled) +// new SubArray(new Array(20)).spliceOne(11) x 1,703,608 ops/sec ±1.43% (79 runs sampled) +// spliceOne(new Array(20), 11) x 6,371,527 ops/sec ±8.68% (71 runs sampled) +// arraySplice(new Array(50), 30) x 2,961,652 ops/sec ±3.94% (81 runs sampled) +// new SubArray(new Array(50)).spliceOne(30) x 1,738,558 ops/sec ±2.28% (84 runs sampled) +// spliceOne(new Array(50), 30) x 2,887,661 ops/sec ±4.01% (74 runs sampled) +// arraySplice(new Array(100), 80) x 2,803,597 ops/sec ±2.12% (86 runs sampled) +// new SubArray(new Array(100)).spliceOne(80) x 1,695,942 ops/sec ±0.91% (88 runs sampled) +// spliceOne(new Array(100), 80) x 3,175,629 ops/sec ±1.28% (86 runs sampled) diff --git a/lib/array.js b/lib/array.js index 98c9a19..038ffd5 100644 --- a/lib/array.js +++ b/lib/array.js @@ -1,8 +1,9 @@ -/*! - * utility - lib/array.js - * - * Copyright(c) 2012 - 2014 fengmk2 +/** + * Copyright(c) node-modules and other contributors. * MIT Licensed + * + * Authors: + * fengmk2 (http://fengmk2.com) */ "use strict"; @@ -27,3 +28,30 @@ exports.randomSlice = function randomSlice(arr, num) { } return a; }; + +/** + * Remove one exists element from an array + * @param {Array} arr + * @param {Number} index - remove element index + * @return {Array} the array instance + */ +exports.spliceOne = function spliceOne(arr, index) { + if (index < 0) { + index = arr.length + index; + // still negative, not found element + if (index < 0) { + return arr; + } + } + + // don't touch + if (index >= arr.length) { + return arr; + } + + for (var i = index, k = i + 1, n = arr.length; k < n; i += 1, k += 1) { + arr[i] = arr[k]; + } + arr.pop(); + return arr; +}; diff --git a/package.json b/package.json index 484ff39..c27dea6 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "lib" ], "scripts": { - "test": "ava test/**/*.test.js", + "test": "npm run lint && ava test/**/*.test.js", "test-cov": "nyc ava test/**/*.test.js && nyc report --reporter=lcov", "lint": "jshint .", "ci": "npm run lint && npm run test-cov", diff --git a/test/array.test.js b/test/array.test.js index cd15ec8..6cfdf91 100644 --- a/test/array.test.js +++ b/test/array.test.js @@ -26,3 +26,24 @@ test('randomSlice() should return sub items', t => { t.deepEqual(utils.randomSlice(arr, 0), arr); t.is(utils.randomSlice(arr, 6).length, 6); }); + +test('spliceOne() should work', t => { + t.deepEqual(utils.spliceOne([1, 2, 3], 0), [2, 3]); + t.deepEqual(utils.spliceOne([1, 2, 3], 1), [1, 3]); + t.deepEqual(utils.spliceOne([1, 2, 3], 2), [1, 2]); + t.deepEqual(utils.spliceOne([1, 2, 3], 3), [1, 2, 3]); + t.deepEqual(utils.spliceOne([1, 2, 3], 4), [1, 2, 3]); + t.deepEqual(utils.spliceOne([1, 2, 3], 5), [1, 2, 3]); + t.deepEqual(utils.spliceOne([1, 2, 3], -0), [2, 3]); + t.deepEqual(utils.spliceOne([1, 2, 3], -1), [1, 2]); + t.deepEqual(utils.spliceOne([1, 2, 3], -2), [1, 3]); + t.deepEqual(utils.spliceOne([1, 2, 3], -3), [2, 3]); + t.deepEqual(utils.spliceOne([1, 2, 3], -4), [1, 2, 3]); + t.deepEqual(utils.spliceOne([1, 2, 3], -5), [1, 2, 3]); + t.deepEqual(utils.spliceOne([1, 2, 3], 100), [1, 2, 3]); + + t.deepEqual(utils.spliceOne([1], 0), []); + t.deepEqual(utils.spliceOne([1], 1), [1]); + t.deepEqual(utils.spliceOne([], 0), []); + t.deepEqual(utils.spliceOne([], 100), []); +});