Skip to content

Commit

Permalink
refactor: convert helper methods
Browse files Browse the repository at this point in the history
  • Loading branch information
AxiosLeo committed Feb 23, 2024
1 parent b388b68 commit 996f689
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 86 deletions.
40 changes: 38 additions & 2 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Color } from 'colors';
import { ChildProcess, SpawnOptionsWithoutStdio } from 'child_process';
import Big from 'big.js';

type Level = number | null | boolean | string;

Expand Down Expand Up @@ -745,8 +746,6 @@ export namespace helper {
function _assign<T>(targetObj: T, ...objs: ObjectItem[]): T;
function _deep_clone(obj: ObjectItem): ObjectItem;
function _deep_clone<T>(obj: T): T;
function _tree2array(tree: any[] | any, options?: Tree2ArrayOptions);
function _array2tree(array: any[], options?: Tree2ArrayOptions);
}

export interface EmitterConfig {
Expand Down Expand Up @@ -871,4 +870,41 @@ export namespace helper {
*/
function _len(str: string): number;
}

type ConvertNumberOptions = {
digits?: string,
length?: number
}

type ConvertNumberResult = {
str: string,
num: Big,
digits: string,
length?: number
}

module convert {
/**
* convert tree to array
* @param tree
* @param options
*/
function _tree2array(tree: any[] | any, options?: Tree2ArrayOptions): any[];

/**
* convert array to tree
* @param array
* @param options
*/
function _array2tree(array: any[], options?: Tree2ArrayOptions): any[];

/**
* convert number to string with specified digits
* @param number
* @param from
* @param to
* @param options default digits is '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
*/
function _number(number: number | string | Big, from: number, to: number, options?: ConvertNumberOptions): ConvertNumberResult;
}
}
89 changes: 77 additions & 12 deletions src/helper/convert.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@

const is = require('./is');
const Big = require('big.js');
const { _assign } = require('./obj');

const defaultDigits = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

/**
* co
* @param {*} num
* @param {string} num
* @param {number} from
* @returns {Big}
*/
function _convertToDecimalist(num, from) {
function _toDecimalist(num, from) {
let len = num.length;
let dec = new Big(0);
let base = new Big(from);
Expand All @@ -31,7 +31,7 @@ function _convertToDecimalist(num, from) {
* @param {string} digits
* @returns {string}
*/
function _convertDecimalist(num, to, digits) {
function _fromDecimalist(num, to, digits) {
let res = '';
let base = new Big(to);
while (num.gt(0)) {
Expand All @@ -43,29 +43,94 @@ function _convertDecimalist(num, to, digits) {
}

/**
* @param {number|string} num
* @param {number|string|Big} num
* @param {number} from
* @param {number} to
* @param {{digits:string,patch:string,length?:number}} options
* @returns {string}
* @returns {{str:string,num:Big,digits:string,length?:number}}
*/
function _convertNumber(num, from, to, options = {}) {
function _number(num, from, to, options = {}) {
if (to > 62) {
throw new Error('target base must be less than 62');
}
if (!is.string(num)) {
num = `${num}`;
let str = num;
if (num instanceof Big) {
str = num.toString();
} else if (is.number(num)) {
str = `${num}`;
}
const digits = options.digits || defaultDigits;
const { length } = options;
let n = from !== 10 ? _convertToDecimalist(num, from) : new Big(num);
let res = _convertDecimalist(n, to, digits);
let n = from !== 10 ? _toDecimalist(str, from) : new Big(str);
let res = _fromDecimalist(n, to, digits);
if (typeof length !== 'undefined' && res.length < length) {
res = digits.charAt(0).repeat(length - res.length) + res;
}
return { str: res, num: n, digits, length };
}

function _array2tree(data, options = {}) {
if (!is.array(data)) {
throw new Error('data must be an array');
}
const c = _assign({
parent_index: 'parent_id',
data_index: 'id',
child_name: 'child'
}, options);

const items = [];
data.forEach(d => {
if (typeof d[c.child_name] === 'undefined') {
d[c.child_name] = [];
} else {
throw new Error('child name "' + c.child_name + '" is reserved for child data, please use another name');
}
items[d[c.data_index]] = d;
if (typeof d[c.parent_index] === 'undefined' || typeof d[c.data_index] === 'undefined') {
throw new Error('data must have "' + c.parent_index + '" and "' + c.data_index + '"');
}
});

const tree = [];
let n = 0;
data.forEach(item => {
if (items[item[c.parent_index]]) {
items[item[c.parent_index]][c.child_name].push(items[item[c.data_index]]);
} else {
tree[n++] = items[item[c.data_index]];
}
});
return tree;
}

function _tree2array(tree, options = {}) {
if (!is.array(tree)) {
tree = [tree];
}
const c = _assign({
parent_index: 'parent_id',
data_index: 'id',
child_name: 'child'
}, options);
const res = [];
function recurse(data, parent_id) {
data.forEach(d => {
const child = d[c.child_name].map(i => i);
delete d[c.child_name];
d[c.parent_index] = parent_id || 0;
res.push(d);
if (child.length) {
recurse(child, d[c.data_index]);
}
});
}
recurse(tree, 0);
return res;
}

module.exports = {
_convertNumber
_number,
_array2tree,
_tree2array,
};
62 changes: 0 additions & 62 deletions src/helper/obj.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,71 +74,9 @@ function _deep_clone(obj) {
return copy;
}

function _array2tree(data, options = {}) {
if (!is.array(data)) {
throw new Error('data must be an array');
}
const c = _assign({
parent_index: 'parent_id',
data_index: 'id',
child_name: 'child'
}, options);

const items = [];
data.forEach(d => {
if (typeof d[c.child_name] === 'undefined') {
d[c.child_name] = [];
} else {
throw new Error('child name "' + c.child_name + '" is reserved for child data, please use another name');
}
items[d[c.data_index]] = d;
if (typeof d[c.parent_index] === 'undefined' || typeof d[c.data_index] === 'undefined') {
throw new Error('data must have "' + c.parent_index + '" and "' + c.data_index + '"');
}
});

const tree = [];
let n = 0;
data.forEach(item => {
if (items[item[c.parent_index]]) {
items[item[c.parent_index]][c.child_name].push(items[item[c.data_index]]);
} else {
tree[n++] = items[item[c.data_index]];
}
});
return tree;
}

function _tree2array(tree, options = {}) {
if (!is.array(tree)) {
tree = [tree];
}
const c = _assign({
parent_index: 'parent_id',
data_index: 'id',
child_name: 'child'
}, options);
const res = [];
function recurse(data, parent_id) {
data.forEach(d => {
const child = d[c.child_name].map(i => i);
delete d[c.child_name];
d[c.parent_index] = parent_id || 0;
res.push(d);
if (child.length) {
recurse(child, d[c.data_index]);
}
});
}
recurse(tree, 0);
return res;
}

module.exports = {
_assign,
_flatten,
_unflatten,
_array2tree,
_tree2array,
_deep_clone
};
21 changes: 12 additions & 9 deletions tests/convert.tests.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
'use strict';

const expect = require('chai').expect;
const _convertNumber = require('../src/helper/convert')._convertNumber;
const Big = require('big.js');
const _number = require('../src/helper/convert')._number;

const digits = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz';

describe('convert test case', function () {
it('convert to decimalist', function () {
expect(_convertNumber(61, 10, 62)).to.be.equal('Z');
expect(_convertNumber(61, 10, 62, { digits })).to.be.equal('z');
expect(_convertNumber('z', 62, 10)).to.be.equal('35');
expect(_convertNumber('z', 62, 10, { digits })).to.be.equal('DF');
expect(_convertNumber('z', 62, 10, { digits, length: 4 })).to.be.equal('AADF');
expect(_convertNumber('ZZZZZZ', 62, 10)).to.be.equal('56800235583');
expect(_number(9999, 10, 10).str).to.be.equal('9999');
expect(_number(new Big(9999), 10, 10).str).to.be.equal('9999');
expect(_number(61, 10, 62).str).to.be.equal('Z');
expect(_number(61, 10, 62, { digits }).str).to.be.equal('z');
expect(_number('z', 62, 10).str).to.be.equal('35');
expect(_number('z', 62, 10, { digits }).str).to.be.equal('DF');
expect(_number('z', 62, 10, { digits, length: 4 }).str).to.be.equal('AADF');
expect(_number('ZZZZZZ', 62, 10).str).to.be.equal('56800235583');
});

it('throw error', function () {
expect(() => _convertNumber('$', 62, 10)).to.throw('Invalid number character: $');
expect(() => _convertNumber('z', 62, 63)).to.throw('target base must be less than 62');
expect(() => _number('$', 62, 10)).to.throw('Invalid number character: $');
expect(() => _number('z', 62, 63)).to.throw('target base must be less than 62');
});
});
3 changes: 2 additions & 1 deletion tests/obj.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

const expect = require('chai').expect;
const { Configuration } = require('..');
const { _deep_clone, _flatten, _unflatten, _array2tree, _tree2array } = require('../src/helper/obj');
const { _deep_clone, _flatten, _unflatten } = require('../src/helper/obj');
const { _array2tree, _tree2array } = require('../src/helper/convert');

describe('obj test case', function () {
it('flatten', function () {
Expand Down

0 comments on commit 996f689

Please sign in to comment.