From 8928ccab1e613f9e606c4f2a203bb64bed7444fb Mon Sep 17 00:00:00 2001 From: vigan-abd Date: Thu, 2 Nov 2023 15:03:13 +0100 Subject: [PATCH 1/2] feat: shuffle function --- CHANGELOG | 3 +++ README.md | 1 + index.d.ts | 1 + index.js | 4 +++- package.json | 2 +- src/shuffle.js | 22 ++++++++++++++++++++++ test/shuffle.js | 18 ++++++++++++++++++ 7 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 src/shuffle.js create mode 100644 test/shuffle.js diff --git a/CHANGELOG b/CHANGELOG index f06bc0f..d8de468 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +# 1.5.0 +- feat: shuffle + # 1.4.0 - feat: isObject diff --git a/README.md b/README.md index f201b3d..748c46a 100644 --- a/README.md +++ b/README.md @@ -18,3 +18,4 @@ Currently supported utils: - `omitBy` - provides new object that omits only specific fields of source object depending on predicate function filter - `pick` - provides new object that picks only specific fields of source object - `pickBy` - provides new object that picks only specific fields of source object depending on predicate function filter +- `shuffle` - performs pseudo random shuffle on clone of the array diff --git a/index.d.ts b/index.d.ts index eec0684..d969ecd 100644 --- a/index.d.ts +++ b/index.d.ts @@ -13,3 +13,4 @@ export function omit(obj: Object, keys: Array): Object export function omitBy(obj: Object, predicate: (val: any, key: string) => boolean): Object export function pick(obj: Object, keys: Array): Object export function pickBy(obj: Object, predicate: (val: any, key: string) => boolean): Object +export function shuffle(array: Array): Array diff --git a/index.js b/index.js index 81a124c..319702a 100644 --- a/index.js +++ b/index.js @@ -15,6 +15,7 @@ const omit = require('./src/omit') const omitBy = require('./src/omitBy') const pick = require('./src/pick') const pickBy = require('./src/pickBy') +const shuffle = require('./src/shuffle') module.exports = { camelize, @@ -31,5 +32,6 @@ module.exports = { omit, omitBy, pick, - pickBy + pickBy, + shuffle } diff --git a/package.json b/package.json index f16b48e..45afed0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@bitfinex/lib-js-util-base", - "version": "1.4.0", + "version": "1.5.0", "description": "general utils", "main": "index.js", "scripts": { diff --git a/src/shuffle.js b/src/shuffle.js new file mode 100644 index 0000000..e28b7a2 --- /dev/null +++ b/src/shuffle.js @@ -0,0 +1,22 @@ +'use strict' + +/** + * Performs pseudo random shuffles on clone of the array + * + * @param {Array} array + * @returns {Array} + */ +const shuffle = (array) => { + const clone = [...array] + const length = clone.length + for (let i = 0; i < length; i++) { + const mov = Math.floor(Math.random() * length) + const tmp = clone[mov] + clone[mov] = clone[i] + clone[i] = tmp + } + + return clone +} + +module.exports = shuffle diff --git a/test/shuffle.js b/test/shuffle.js new file mode 100644 index 0000000..817654e --- /dev/null +++ b/test/shuffle.js @@ -0,0 +1,18 @@ +'use strict' + +/* eslint-env mocha */ + +const assert = require('assert') +const { shuffle } = require('../index') + +describe('shuffle', () => { + const array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + + it('should return a new array', () => { + assert.ok(shuffle(array).some((x, i) => array[i] !== x)) + }) + + it('should contain the same elements after a collection is shuffled', () => { + assert.deepStrictEqual(shuffle(array).sort((a, b) => a - b), array) + }) +}) From 1aa1b9bb787a48789d8caa829d16ce79af585c17 Mon Sep 17 00:00:00 2001 From: vigan-abd Date: Thu, 2 Nov 2023 16:45:38 +0100 Subject: [PATCH 2/2] replace shuffle --- src/shuffle.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/shuffle.js b/src/shuffle.js index e28b7a2..e8e9ecb 100644 --- a/src/shuffle.js +++ b/src/shuffle.js @@ -9,11 +9,9 @@ const shuffle = (array) => { const clone = [...array] const length = clone.length - for (let i = 0; i < length; i++) { - const mov = Math.floor(Math.random() * length) - const tmp = clone[mov] - clone[mov] = clone[i] - clone[i] = tmp + for (let i = length - 1; i > 0; i--) { + const index = Math.floor(Math.random() * (i + 1)); // random index from 0 to i + [clone[i], clone[index]] = [clone[index], clone[i]] // swap elements } return clone