foreslash 0.3.2 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/lib/index.cmn.cjs +257 -4
- package/lib/index.d.ts +218 -26
- package/lib/index.mjs +252 -5
- package/lib/index.umd.js +257 -4
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
## Version 0.3.3 - 2025-11-05
|
|
4
|
+
|
|
5
|
+
Unstable version
|
|
6
|
+
|
|
7
|
+
- Feat 🥥 Functions added: `lerp` `scientificNotation` `castArray` `romanNumerals` `randomDistribution` and so forth
|
|
8
|
+
- Fix 🥕 Document: Added version tags to `memo` and description to several methods
|
|
9
|
+
- Other fixes and improvements
|
|
10
|
+
|
|
11
|
+
不稳定版本
|
|
12
|
+
|
|
13
|
+
- 功能 🥥 添加函数: `lerp` `scientificNotation` `castArray` `randomDistribution` 等
|
|
14
|
+
- 修复 🥕 文档: 补充 `memo` 的版本标签和部分方法的说明
|
|
15
|
+
- 其他修复与优化
|
|
16
|
+
|
|
3
17
|
## Version 0.3.2 - 2025-09-23
|
|
4
18
|
|
|
5
19
|
Unstable version
|
package/lib/index.cmn.cjs
CHANGED
|
@@ -45,6 +45,10 @@ function cartesianProduct(...arrList) {
|
|
|
45
45
|
return res;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
function castArray(value) {
|
|
49
|
+
return Array.isArray(value) ? value.slice() : [value];
|
|
50
|
+
}
|
|
51
|
+
|
|
48
52
|
function chunk(array, size = 2) {
|
|
49
53
|
const res = [];
|
|
50
54
|
if (size < 1 || isNaN(size))
|
|
@@ -609,6 +613,201 @@ function format(num, options) {
|
|
|
609
613
|
return sign + integer;
|
|
610
614
|
}
|
|
611
615
|
|
|
616
|
+
function lerp(val1, val2, t) {
|
|
617
|
+
if (isNumber(val1)) {
|
|
618
|
+
if (!isNumber(val2))
|
|
619
|
+
throw new Error('Invalid val2 parameter: val2 should be a number');
|
|
620
|
+
return _lerp(val1, val2, t);
|
|
621
|
+
}
|
|
622
|
+
else if (isArray(val1)) {
|
|
623
|
+
if (!isArray(val2))
|
|
624
|
+
throw new Error('Invalid val2 parameter: val2 should be an Array');
|
|
625
|
+
if (val1.length !== val2.length) {
|
|
626
|
+
throw new Error(`Invalid val2 parameter: the length of val2 (${val2.length}) should be consistent with val1 (${val1.length})`);
|
|
627
|
+
}
|
|
628
|
+
if (val1.length === 0)
|
|
629
|
+
return [];
|
|
630
|
+
if (isNumber(val1[0])) {
|
|
631
|
+
if (!isNumber(val2[0]))
|
|
632
|
+
throw new Error('Invalid val2 parameter: val2 should be an Array<number>');
|
|
633
|
+
return val1.map((v1, index) => _lerp(v1, val2[index], t));
|
|
634
|
+
}
|
|
635
|
+
else if (isArray(val1[0])) {
|
|
636
|
+
const res = [];
|
|
637
|
+
for (let i = 0; i < val1.length; i++) {
|
|
638
|
+
const arr1 = val1[i];
|
|
639
|
+
const arr2 = val2[i];
|
|
640
|
+
if (arr1.length !== arr2.length) {
|
|
641
|
+
throw new Error(`Invalid val2 parameter: The length of array at index ${i} in val2 (${arr2.length}) must match the length of the corresponding array in val1 (${arr1.length})`);
|
|
642
|
+
}
|
|
643
|
+
res.push(arr1.map((v1, index) => _lerp(v1, arr2[index], t)));
|
|
644
|
+
}
|
|
645
|
+
return res;
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
throw new Error('Invalid val1 parameter: val1 should be a number or Array');
|
|
649
|
+
}
|
|
650
|
+
function _lerp(val1, val2, t) {
|
|
651
|
+
return val1 + (val2 - val1) * t;
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
function romanNumerals(num, options) {
|
|
655
|
+
const str = decimalNotation(num);
|
|
656
|
+
if (/NaN|Inf/.test(str))
|
|
657
|
+
return str;
|
|
658
|
+
const type = (options || {}).type || 'unicode';
|
|
659
|
+
const thousand = (options || {}).thousand || 'normal';
|
|
660
|
+
const forceSplitThousand = thousand === 'strict';
|
|
661
|
+
const integer = str.split('.')[0].replace('-', '');
|
|
662
|
+
if (integer === '0') {
|
|
663
|
+
const zero = (options || {}).zero || '0';
|
|
664
|
+
if (type === 'json')
|
|
665
|
+
return `["${zero}"]`;
|
|
666
|
+
else
|
|
667
|
+
return zero;
|
|
668
|
+
}
|
|
669
|
+
if (integer === '1') {
|
|
670
|
+
const one = (options || {}).one || 'I';
|
|
671
|
+
if (type === 'json')
|
|
672
|
+
return `["${one}"]`;
|
|
673
|
+
else
|
|
674
|
+
return one;
|
|
675
|
+
}
|
|
676
|
+
const chunks = chunk(Array.from(integer).reverse(), 3);
|
|
677
|
+
const romanChunks = [];
|
|
678
|
+
for (let i = 0; i < chunks.length; i++) {
|
|
679
|
+
const val = Number(chunks[i].reverse().join(''));
|
|
680
|
+
if (i === chunks.length - 2 && !forceSplitThousand && Number(chunks[i + 1]) < 4) {
|
|
681
|
+
romanChunks.push(number2roman(val + Number(chunks[i + 1]) * 1000));
|
|
682
|
+
break;
|
|
683
|
+
}
|
|
684
|
+
else {
|
|
685
|
+
romanChunks.push(number2roman(val));
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
switch (type) {
|
|
689
|
+
case 'js':
|
|
690
|
+
return romanChunks
|
|
691
|
+
.map((str, index) => str
|
|
692
|
+
.split('')
|
|
693
|
+
.map((s) => s + '\\\\u0305'.repeat(index))
|
|
694
|
+
.join(''))
|
|
695
|
+
.reverse()
|
|
696
|
+
.join('');
|
|
697
|
+
case 'html':
|
|
698
|
+
return romanChunks
|
|
699
|
+
.map((str, index) => str
|
|
700
|
+
.split('')
|
|
701
|
+
.map((s) => s + '̅'.repeat(index))
|
|
702
|
+
.join(''))
|
|
703
|
+
.reverse()
|
|
704
|
+
.join('');
|
|
705
|
+
case 'json':
|
|
706
|
+
return `[${romanChunks.map((str) => `"${str}"`).join(', ')}]`;
|
|
707
|
+
case 'unicode':
|
|
708
|
+
default:
|
|
709
|
+
return romanChunks
|
|
710
|
+
.map((str, index) => str
|
|
711
|
+
.split('')
|
|
712
|
+
.map((s) => s + '\u0305'.repeat(index))
|
|
713
|
+
.join(''))
|
|
714
|
+
.reverse()
|
|
715
|
+
.join('');
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
function number2roman(num) {
|
|
719
|
+
const symbols = [
|
|
720
|
+
[1000, 'M'],
|
|
721
|
+
[900, 'CM'],
|
|
722
|
+
[500, 'D'],
|
|
723
|
+
[400, 'CD'],
|
|
724
|
+
[100, 'C'],
|
|
725
|
+
[90, 'XC'],
|
|
726
|
+
[50, 'L'],
|
|
727
|
+
[40, 'XL'],
|
|
728
|
+
[10, 'X'],
|
|
729
|
+
[9, 'IX'],
|
|
730
|
+
[5, 'V'],
|
|
731
|
+
[4, 'IV'],
|
|
732
|
+
[1, 'I'],
|
|
733
|
+
];
|
|
734
|
+
let roman = '';
|
|
735
|
+
for (const [val, str] of symbols) {
|
|
736
|
+
while (num >= val) {
|
|
737
|
+
num -= val;
|
|
738
|
+
roman += str;
|
|
739
|
+
}
|
|
740
|
+
if (num == 0)
|
|
741
|
+
break;
|
|
742
|
+
}
|
|
743
|
+
return roman;
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
function scientificNotation(num, options) {
|
|
747
|
+
const str = decimalNotation(num);
|
|
748
|
+
if (/NaN|Inf/.test(str))
|
|
749
|
+
return str;
|
|
750
|
+
const type = (options || {}).type || 'unicode';
|
|
751
|
+
const _precision = (options || {}).precision;
|
|
752
|
+
const precision = isNumber(_precision) ? clamp(_precision !== null && _precision !== void 0 ? _precision : 2, 0, Infinity) : null;
|
|
753
|
+
const round = (options || {}).round || 'round';
|
|
754
|
+
let [integer, fractional] = str.split('.');
|
|
755
|
+
let sign = '';
|
|
756
|
+
if (/^-/.test(integer)) {
|
|
757
|
+
integer = integer.substring(1);
|
|
758
|
+
sign = '-';
|
|
759
|
+
}
|
|
760
|
+
fractional = fractional !== null && fractional !== void 0 ? fractional : '';
|
|
761
|
+
let exp = 0;
|
|
762
|
+
let n = '';
|
|
763
|
+
if (integer === '0') {
|
|
764
|
+
exp = /^(0+)/.test(fractional) ? -(fractional.match(/^(0+)/)[0].length + 1) : -1;
|
|
765
|
+
[integer, fractional] = [fractional.slice(-exp - 1, -exp), fractional.slice(-exp)];
|
|
766
|
+
}
|
|
767
|
+
else {
|
|
768
|
+
exp = integer.length - 1;
|
|
769
|
+
[integer, fractional] = [integer.slice(0, 1), integer.slice(1) + fractional];
|
|
770
|
+
}
|
|
771
|
+
if (isNumber(precision)) {
|
|
772
|
+
if (fractional.length > precision) {
|
|
773
|
+
const roundMap = { round: roundBase, banker: roundBank, floor: roundFloor, ceil: roundCeil };
|
|
774
|
+
[integer, fractional] = (roundMap[round] || roundBase)(integer, fractional, precision, !!sign);
|
|
775
|
+
}
|
|
776
|
+
else if (fractional.length < precision) {
|
|
777
|
+
fractional += '0'.repeat(precision - fractional.length);
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
else {
|
|
781
|
+
fractional = fractional.replace(/0+$/, '');
|
|
782
|
+
}
|
|
783
|
+
if ((precision === null && fractional) || (isNumber(precision) && precision > 0)) {
|
|
784
|
+
n = sign + integer + '.' + fractional;
|
|
785
|
+
}
|
|
786
|
+
else
|
|
787
|
+
n = sign + integer;
|
|
788
|
+
switch (type) {
|
|
789
|
+
case 'exp':
|
|
790
|
+
return `${n}e${exp < 0 ? '' : '+'}${exp}`;
|
|
791
|
+
case 'js':
|
|
792
|
+
return `${n}*10**${exp}`;
|
|
793
|
+
case 'code':
|
|
794
|
+
return `${n}*10^${exp}`;
|
|
795
|
+
case 'html':
|
|
796
|
+
return `${n}×10<sup>${exp}</sup>`;
|
|
797
|
+
case 'json':
|
|
798
|
+
return `{"number":"${n}","exp":${exp}}`;
|
|
799
|
+
case 'unicode':
|
|
800
|
+
default:
|
|
801
|
+
return `${n}×10${transferNumberToUniCode(String(exp))}`;
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
function transferNumberToUniCode(n) {
|
|
805
|
+
const strMap = Object.assign(Object.assign({}, Array.from('⁰¹²³⁴⁵⁶⁷⁸⁹')), { '-': '⁻', '+': '⁺' });
|
|
806
|
+
return Array.from(n)
|
|
807
|
+
.map((s) => (strMap[s] ? strMap[s] : s))
|
|
808
|
+
.join('');
|
|
809
|
+
}
|
|
810
|
+
|
|
612
811
|
function parallel(args, fn, options) {
|
|
613
812
|
return __awaiter(this, void 0, void 0, function* () {
|
|
614
813
|
if (!args.length)
|
|
@@ -1240,6 +1439,54 @@ function randomChoice(arr, weights) {
|
|
|
1240
1439
|
return arr[index];
|
|
1241
1440
|
}
|
|
1242
1441
|
|
|
1442
|
+
function randomDistribution(p, options) {
|
|
1443
|
+
const threshold = (options === null || options === void 0 ? void 0 : options.threshold) ? Math.max(options.threshold, Number.MIN_VALUE * 2) : 5e-6;
|
|
1444
|
+
const C = getInitP(p, threshold);
|
|
1445
|
+
let current = C;
|
|
1446
|
+
return function getRandomDistribution() {
|
|
1447
|
+
const res = Math.random() < current;
|
|
1448
|
+
if (res)
|
|
1449
|
+
current = C;
|
|
1450
|
+
else
|
|
1451
|
+
current += C;
|
|
1452
|
+
return res;
|
|
1453
|
+
};
|
|
1454
|
+
}
|
|
1455
|
+
function getInitP(targetP, threshold = 5e-6) {
|
|
1456
|
+
if (targetP <= 0)
|
|
1457
|
+
return 0;
|
|
1458
|
+
if (targetP >= 1)
|
|
1459
|
+
return 1;
|
|
1460
|
+
let [down, up] = [0, 1];
|
|
1461
|
+
let mid = 1;
|
|
1462
|
+
let tempP = 1;
|
|
1463
|
+
let tempPLast = 1;
|
|
1464
|
+
let step = 64;
|
|
1465
|
+
while (step-- > 0) {
|
|
1466
|
+
mid = (down + up) / 2;
|
|
1467
|
+
tempP = getRealPFromInitP(mid);
|
|
1468
|
+
if (Math.abs(tempPLast - tempP) < threshold)
|
|
1469
|
+
break;
|
|
1470
|
+
if (tempP > targetP)
|
|
1471
|
+
up = mid;
|
|
1472
|
+
else
|
|
1473
|
+
down = mid;
|
|
1474
|
+
}
|
|
1475
|
+
return mid;
|
|
1476
|
+
}
|
|
1477
|
+
function getRealPFromInitP(initP) {
|
|
1478
|
+
let sum = 0;
|
|
1479
|
+
let prod = 0;
|
|
1480
|
+
let cur = 0;
|
|
1481
|
+
let max = Math.ceil(1 / initP);
|
|
1482
|
+
for (let n = 1; n <= max; n++) {
|
|
1483
|
+
cur = Math.min(1, n * initP) * (1 - prod);
|
|
1484
|
+
prod += cur;
|
|
1485
|
+
sum += n * cur;
|
|
1486
|
+
}
|
|
1487
|
+
return 1 / sum;
|
|
1488
|
+
}
|
|
1489
|
+
|
|
1243
1490
|
const radix32 = '0123456789abcdefghijklmnopqrstuv';
|
|
1244
1491
|
const base32Chars = 'abcdefghijklmnopqrstuvwxyz234567';
|
|
1245
1492
|
const base32Crockford = '0123456789abcdefghjkmnpqrstvwxyz';
|
|
@@ -1866,22 +2113,22 @@ function _deepClone(obj, map, options) {
|
|
|
1866
2113
|
if (isFormData(obj))
|
|
1867
2114
|
return _cloneFormData(obj, map, _deepClone, options);
|
|
1868
2115
|
let res;
|
|
1869
|
-
if (obj
|
|
2116
|
+
if (isDate(obj)) {
|
|
1870
2117
|
res = new Date(obj.valueOf());
|
|
1871
2118
|
map.set(obj, res);
|
|
1872
2119
|
}
|
|
1873
|
-
else if (obj
|
|
2120
|
+
else if (isRegExp(obj)) {
|
|
1874
2121
|
res = new RegExp(obj.source, obj.flags);
|
|
1875
2122
|
map.set(obj, res);
|
|
1876
2123
|
}
|
|
1877
|
-
else if (obj
|
|
2124
|
+
else if (isArrayBuffer(obj)) {
|
|
1878
2125
|
res = _cloneArrayBuffer(obj, map);
|
|
1879
2126
|
}
|
|
1880
2127
|
else if (isTypedArray(obj)) {
|
|
1881
2128
|
res = new obj.constructor(_cloneArrayBuffer(obj.buffer, map), obj.byteOffset, obj.length);
|
|
1882
2129
|
map.set(obj, res);
|
|
1883
2130
|
}
|
|
1884
|
-
else if (obj
|
|
2131
|
+
else if (isDataView(obj)) {
|
|
1885
2132
|
res = new DataView(map.has(obj.buffer) ? map.get(obj.buffer) : _cloneArrayBuffer(obj.buffer, map), obj.byteOffset, obj.byteLength);
|
|
1886
2133
|
map.set(obj, res);
|
|
1887
2134
|
}
|
|
@@ -2289,6 +2536,7 @@ exports.caseConvert = caseConvert;
|
|
|
2289
2536
|
exports.caseKebab = caseKebab;
|
|
2290
2537
|
exports.casePascal = casePascal;
|
|
2291
2538
|
exports.caseSnake = caseSnake;
|
|
2539
|
+
exports.castArray = castArray;
|
|
2292
2540
|
exports.chunk = chunk;
|
|
2293
2541
|
exports.clamp = clamp;
|
|
2294
2542
|
exports.compose = compose;
|
|
@@ -2304,6 +2552,7 @@ exports.format = format;
|
|
|
2304
2552
|
exports.getAcceptableExtByMIME = getAcceptableExtByMIME;
|
|
2305
2553
|
exports.getAcceptableMIMEByExt = getAcceptableMIMEByExt;
|
|
2306
2554
|
exports.getGlobalThis = getGlobalThis;
|
|
2555
|
+
exports.getInitP = getInitP;
|
|
2307
2556
|
exports.getTag = getTag;
|
|
2308
2557
|
exports.indent = indent;
|
|
2309
2558
|
exports.isArray = isArray;
|
|
@@ -2360,6 +2609,7 @@ exports.isWrapperObject = isWrapperObject;
|
|
|
2360
2609
|
exports.isWrapperString = isWrapperString;
|
|
2361
2610
|
exports.isWrapperSymbol = isWrapperSymbol;
|
|
2362
2611
|
exports.kebabCase = kebabCase;
|
|
2612
|
+
exports.lerp = lerp;
|
|
2363
2613
|
exports.memo = memo;
|
|
2364
2614
|
exports.noop = noop;
|
|
2365
2615
|
exports.not = not;
|
|
@@ -2370,6 +2620,7 @@ exports.passWith = passWith;
|
|
|
2370
2620
|
exports.pipe = pipe;
|
|
2371
2621
|
exports.randomBase32String = randomBase32String;
|
|
2372
2622
|
exports.randomChoice = randomChoice;
|
|
2623
|
+
exports.randomDistribution = randomDistribution;
|
|
2373
2624
|
exports.randomHexString = randomHexString;
|
|
2374
2625
|
exports.randomInt = randomInt;
|
|
2375
2626
|
exports.randomIntFloor = randomIntFloor;
|
|
@@ -2377,11 +2628,13 @@ exports.randomString = randomString;
|
|
|
2377
2628
|
exports.range = range;
|
|
2378
2629
|
exports.remove = remove;
|
|
2379
2630
|
exports.retry = retry;
|
|
2631
|
+
exports.romanNumerals = romanNumerals;
|
|
2380
2632
|
exports.round = round;
|
|
2381
2633
|
exports.roundBank = roundBank;
|
|
2382
2634
|
exports.roundBase = roundBase;
|
|
2383
2635
|
exports.roundCeil = roundCeil;
|
|
2384
2636
|
exports.roundFloor = roundFloor;
|
|
2637
|
+
exports.scientificNotation = scientificNotation;
|
|
2385
2638
|
exports.shuffle = shuffle;
|
|
2386
2639
|
exports.sleep = sleep;
|
|
2387
2640
|
exports.snakeCase = snakeCase;
|
package/lib/index.d.ts
CHANGED
|
@@ -24,6 +24,56 @@ declare function cartesianProduct<T1, T2, T3, T4, T5, T6, T7>(arr1: ArrayLike<T1
|
|
|
24
24
|
declare function cartesianProduct<T1, T2, T3, T4, T5, T6, T7, T8>(arr1: ArrayLike<T1>, arr2: ArrayLike<T2>, arr3: ArrayLike<T3>, arr4: ArrayLike<T4>, arr5: ArrayLike<T5>, arr6: ArrayLike<T6>, arr7: ArrayLike<T7>, arr8: ArrayLike<T8>): [T1, T2, T3, T4, T5, T6, T7, T8][];
|
|
25
25
|
declare function cartesianProduct(...arrList: ArrayLike<any>[]): any[][];
|
|
26
26
|
|
|
27
|
+
/**
|
|
28
|
+
* 将值转换为一个数组
|
|
29
|
+
* @param value 需要处理的值
|
|
30
|
+
* @returns 一个数组, 如果输入值是数组, 则输出的数组是其**浅拷贝**; 如果输入不是数组,则将输入包进一个新数组里
|
|
31
|
+
* @example
|
|
32
|
+
* ```js
|
|
33
|
+
* // 如果输入不是数组,则将输入包进一个新数组里
|
|
34
|
+
* castArray(1) // [1]
|
|
35
|
+
* castArray('1') // ['1']
|
|
36
|
+
* castArray(null) // [null]
|
|
37
|
+
*
|
|
38
|
+
* // 如果输入值是数组, 则输出的数组是其浅拷贝
|
|
39
|
+
* castArray([1, 2, 3, 4, 5]) // [1, 2, 3, 4, 5]
|
|
40
|
+
* ```
|
|
41
|
+
* @version 0.3.3
|
|
42
|
+
*/
|
|
43
|
+
declare function castArray<T>(value: T): CastArray<T>;
|
|
44
|
+
/**
|
|
45
|
+
* 将任意输入处理为数组:
|
|
46
|
+
* 1. `never` 类型判断, 确保 `castArray<never>` 返回 `never[]` 而不是 `unknown[]`
|
|
47
|
+
* 2. `unknown` 类型判断, `unknown` 是顶级类型, 需要特殊处理
|
|
48
|
+
* 3. `readonly any[]` 类型判断, 输出的类型需要去除 `readonly`
|
|
49
|
+
* 4. 非数组类型判断, 处理联合类型
|
|
50
|
+
*
|
|
51
|
+
* 数组类型判据:
|
|
52
|
+
* - 如果 `Exclude<T, readonly any[]> extends never` 意味着 `T` 的类型与 `any[]` 兼容, 此时应该走逻辑 3
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```ts
|
|
56
|
+
* type T = CastArray<string> // string[]
|
|
57
|
+
* type T = CastArray<string[]> // string[]
|
|
58
|
+
* type T = CastArray<readonly string[]> // string[]
|
|
59
|
+
* // 特殊类型
|
|
60
|
+
* type T = CastArray<any> // any[]
|
|
61
|
+
* type T = CastArray<unknown> // unknown[]
|
|
62
|
+
* type T = CastArray<never> // never[]
|
|
63
|
+
* // 联合类型
|
|
64
|
+
* type T = CastArray<string | number> // (string | number)[]
|
|
65
|
+
* type T = CastArray<string[] | number> // string[] | number[]
|
|
66
|
+
* type T = CastArray<string | number | never> // (string | number)[]
|
|
67
|
+
* type T = CastArray<string | number[] | never[]> // never[] | number[] | string[]
|
|
68
|
+
* type T = CastArray<string | number | never[]> // never[] | (string | number)[]
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
type CastArray<T> = [
|
|
72
|
+
T
|
|
73
|
+
] extends [never] ? never[] : [
|
|
74
|
+
unknown
|
|
75
|
+
] extends [T] ? unknown[] : (T extends readonly (infer U)[] ? U[] : never) | (Exclude<T, readonly any[]> extends never ? never : Exclude<T, readonly any[]>[]);
|
|
76
|
+
|
|
27
77
|
type Not<T> = T extends false | 0 | '' | null | undefined ? true : false;
|
|
28
78
|
|
|
29
79
|
type Stringify<T extends string | number | boolean | bigint | null | undefined> = `${T}`;
|
|
@@ -253,24 +303,6 @@ declare function retry<T>(asyncFunction: RetryFunction<T>, option?: RetryOption)
|
|
|
253
303
|
declare function sleep(time?: number): Promise<unknown>;
|
|
254
304
|
|
|
255
305
|
type TryitResult<Res, Err> = [undefined, Res] | [Err, undefined];
|
|
256
|
-
/**
|
|
257
|
-
* 将一个函数处理为 `error-first` 的函数
|
|
258
|
-
* @param fn 需要处理的函数, 可以是异步函数
|
|
259
|
-
* @returns 处理过的函数, 调用后返回一个 `error-first` 的元组 `[error, result]`;\
|
|
260
|
-
* 如果原函数是异步函数, 则返回值会是 `Promise<[error, result]>`;\
|
|
261
|
-
* 如果运行正常则 `result` 是原函数的返回值, `error` 为 `undefined`;\
|
|
262
|
-
* 如果出现异常则 `result` 为 `undefined`, `error` 是原函数抛出的错误
|
|
263
|
-
* @example
|
|
264
|
-
* ```js
|
|
265
|
-
* // Async Function
|
|
266
|
-
* const normalAsyncFn = () => { return Promise.resolve(1) }
|
|
267
|
-
* const errorAsyncFn = () => { return Promise.reject('1') }
|
|
268
|
-
* tryit(normalAsyncFn)() // Promise<[undefined, 1]>
|
|
269
|
-
* tryit(errorAsyncFn)() // Promise<[Error('1'), undefined]>
|
|
270
|
-
* ```
|
|
271
|
-
* @version 0.2.0
|
|
272
|
-
*/
|
|
273
|
-
declare function tryit<Args extends any[], Res, Err extends Error>(fn: (...args: Args) => Promise<Res>): (...args: Args) => Promise<TryitResult<Res, Err>>;
|
|
274
306
|
/**
|
|
275
307
|
* 将一个函数处理为 `error-first` 的函数
|
|
276
308
|
* @param fn 需要处理的函数, 可以是异步函数
|
|
@@ -285,9 +317,15 @@ declare function tryit<Args extends any[], Res, Err extends Error>(fn: (...args:
|
|
|
285
317
|
* const errorFn = () => { throw new Error('1') }
|
|
286
318
|
* tryit(normalFn)() // [undefined, 1]
|
|
287
319
|
* tryit(errorFn)() // [Error('1'), undefined]
|
|
320
|
+
* // Async Function
|
|
321
|
+
* const normalAsyncFn = () => { return Promise.resolve(1) }
|
|
322
|
+
* const errorAsyncFn = () => { return Promise.reject(new Error('1')) }
|
|
323
|
+
* tryit(normalAsyncFn)() // Promise<[undefined, 1]>
|
|
324
|
+
* tryit(errorAsyncFn)() // Promise<[Error('1'), undefined]>
|
|
288
325
|
* ```
|
|
289
326
|
* @version 0.2.0
|
|
290
327
|
*/
|
|
328
|
+
declare function tryit<Args extends any[], Res, Err extends Error>(fn: (...args: Args) => Promise<Res>): (...args: Args) => Promise<TryitResult<Res, Err>>;
|
|
291
329
|
declare function tryit<Args extends any[], Res, Err extends Error>(fn: (...args: Args) => Res): (...args: Args) => TryitResult<Res, Err>;
|
|
292
330
|
|
|
293
331
|
interface PromiseLikeConstructor {
|
|
@@ -963,14 +1001,15 @@ declare function clamp(num: number, min: number, max: number, options?: {
|
|
|
963
1001
|
declare function decimalNotation(num: string | number): string;
|
|
964
1002
|
|
|
965
1003
|
/**
|
|
966
|
-
* 将一个数字转换为指定的格式(如千分位逗号分隔)
|
|
1004
|
+
* 将一个数字转换为指定的格式(如千分位逗号分隔)\
|
|
1005
|
+
* 如果想要将数字转换为科学计数法, 请使用 `scientificNotation`
|
|
967
1006
|
* @param num 需要格式化的数字
|
|
968
1007
|
* @param options 格式化配置\
|
|
969
|
-
*
|
|
970
|
-
*
|
|
971
|
-
*
|
|
972
|
-
*
|
|
973
|
-
*
|
|
1008
|
+
* `separator` 分割符, 默认为 `','`\
|
|
1009
|
+
* `separate` 按位分割, 默认为 `3`\
|
|
1010
|
+
* `decimal` 小数点, 默认为 `'.'`\
|
|
1011
|
+
* `precision` 小数精度, 默认为 `2`\
|
|
1012
|
+
* `round` 数值修约规则
|
|
974
1013
|
* - `'round'` 四舍五入
|
|
975
1014
|
* - `'banker'` 四舍六入五成双
|
|
976
1015
|
* - `'floor'` 向下取整
|
|
@@ -1001,6 +1040,84 @@ declare function isOdd(num: number): boolean;
|
|
|
1001
1040
|
*/
|
|
1002
1041
|
declare function isEven(num: number): boolean;
|
|
1003
1042
|
|
|
1043
|
+
/**
|
|
1044
|
+
* 用线性插值法求取一个中间值
|
|
1045
|
+
* @param val1 第一个值, 当 权重=0 时返回的将是这个值, 可以是数组或二维数组
|
|
1046
|
+
* @param val2 第二个值, 当 权重=0 时返回的将是这个值, 可以是数组或二维数组
|
|
1047
|
+
* @param t 权重
|
|
1048
|
+
* @example
|
|
1049
|
+
* ```js
|
|
1050
|
+
* // 传入数值
|
|
1051
|
+
* lerp(1, 2, 0) // 1
|
|
1052
|
+
* lerp(1, 2, 0.5) // 1.5
|
|
1053
|
+
* lerp(1, 2, 1) // 2
|
|
1054
|
+
* lerp(1, 2, 3) // 4
|
|
1055
|
+
*
|
|
1056
|
+
* // 传入数组(数组长度必须一致否则会报错)
|
|
1057
|
+
* lerp([1, 2], [2, 4], 0.5) // [1.5, 3]
|
|
1058
|
+
*
|
|
1059
|
+
* // 传入二维数组(数组长度必须一致否则会报错)
|
|
1060
|
+
* lerp(
|
|
1061
|
+
* [
|
|
1062
|
+
* [1, 2],
|
|
1063
|
+
* [3, 4],
|
|
1064
|
+
* ],
|
|
1065
|
+
* [
|
|
1066
|
+
* [11, 12],
|
|
1067
|
+
* [13, 14],
|
|
1068
|
+
* ],
|
|
1069
|
+
* 0.5
|
|
1070
|
+
* )
|
|
1071
|
+
* // [
|
|
1072
|
+
* // [6, 7],
|
|
1073
|
+
* // [8, 9],
|
|
1074
|
+
* // ]
|
|
1075
|
+
* ```
|
|
1076
|
+
* @version 0.3.3
|
|
1077
|
+
*/
|
|
1078
|
+
declare function lerp(val1: number, val2: number, t: number): number;
|
|
1079
|
+
declare function lerp(val1: [number], val2: [number], t: number): [number];
|
|
1080
|
+
declare function lerp(val1: [number, number], val2: [number, number], t: number): [number, number];
|
|
1081
|
+
declare function lerp(val1: [number, number, number], val2: [number, number, number], t: number): [number, number, number];
|
|
1082
|
+
declare function lerp(val1: [number, number, number, number], val2: [number, number, number, number], t: number): [number, number, number, number];
|
|
1083
|
+
declare function lerp(val1: [number, number, number, number, number], val2: [number, number, number, number, number], t: number): [number, number, number, number, number];
|
|
1084
|
+
declare function lerp(val1: [number, number, number, number, number, number], val2: [number, number, number, number, number, number], t: number): [number, number, number, number, number, number];
|
|
1085
|
+
declare function lerp(val1: [number, number, number, number, number, number, number], val2: [number, number, number, number, number, number, number], t: number): [number, number, number, number, number, number, number];
|
|
1086
|
+
declare function lerp(val1: [number, number, number, number, number, number, number, number], val2: [number, number, number, number, number, number, number, number], t: number): [number, number, number, number, number, number, number, number];
|
|
1087
|
+
declare function lerp(val1: number[], val2: number[], t: number): number[];
|
|
1088
|
+
declare function lerp(val1: number[][], val2: number[][], t: number): number[][];
|
|
1089
|
+
|
|
1090
|
+
/**
|
|
1091
|
+
* 将一个数字转换为罗马数字, 罗马数字没有 `0`、小数和负数
|
|
1092
|
+
* @param num 需要转换的数字
|
|
1093
|
+
* @param options 格式化配置\
|
|
1094
|
+
* `type` 类型, 默认为 `unicode`, 以数字 `4090` 为例
|
|
1095
|
+
* - `'unicode'` 使用 Unicode 表示 `'I̅V̅XC'`
|
|
1096
|
+
* - `'js'` 适合用于 JavaScript 代码字符串 `'I\\u0305V\\u0305XC'`
|
|
1097
|
+
* - `'html'` 适合用于 HTML 展示的字符串 `'I̅V̅XC'`
|
|
1098
|
+
* - `'json'` 一个 JSON 字符串, 具体数值是下标^1000 `["XC", "IV"]`
|
|
1099
|
+
*
|
|
1100
|
+
* `thousand` 千分位类型, 默认为 `normal`
|
|
1101
|
+
* - `'normal'` 习惯用法, 超过 3999 的部分才使用上划线区分
|
|
1102
|
+
* - `'strict'` 严格区分千分位
|
|
1103
|
+
*
|
|
1104
|
+
* `zero` 用什么字符串表示 `0` (罗马数字里没有 `0`), 不填默认为 `'0'`\
|
|
1105
|
+
* `one` 用什么字符串表示 `1` (你可以设置一个彩蛋, 比如输出 `Yo`), 不填默认为 `'I'`, 这项**只会影响数字 1**
|
|
1106
|
+
* @returns 返回一个罗马数字表示的数字
|
|
1107
|
+
* @example
|
|
1108
|
+
* ```js
|
|
1109
|
+
* romanNumerals(2025) // MMXXV
|
|
1110
|
+
* romanNumerals(2025, { thousand: 'strict' }) // I̅I̅XXV
|
|
1111
|
+
* ```
|
|
1112
|
+
* @version 0.3.3
|
|
1113
|
+
*/
|
|
1114
|
+
declare function romanNumerals(num: string | number, options?: {
|
|
1115
|
+
type?: 'unicode' | 'js' | 'html' | 'json';
|
|
1116
|
+
thousand?: 'normal' | 'strict';
|
|
1117
|
+
zero?: string;
|
|
1118
|
+
one?: string;
|
|
1119
|
+
}): string;
|
|
1120
|
+
|
|
1004
1121
|
/**
|
|
1005
1122
|
* 数值修约, 可以使用 4 种修约方法, 默认使用四舍五入
|
|
1006
1123
|
* - 四舍五入: 修约位置的后一位如果是 5 则进位, 否则不进位
|
|
@@ -1106,6 +1223,51 @@ declare function roundFloor(integer: string, fractional: string, precision: numb
|
|
|
1106
1223
|
*/
|
|
1107
1224
|
declare function roundCeil(integer: string, fractional: string, precision: number, isNegative: boolean): [integer: string, fractional: string];
|
|
1108
1225
|
|
|
1226
|
+
/**
|
|
1227
|
+
* 将一个数字转换为科学计数法
|
|
1228
|
+
* @param num 需要转换的数字
|
|
1229
|
+
* @param options 格式化配置\
|
|
1230
|
+
* `type` 类型, 默认为 `unicode`
|
|
1231
|
+
* - `'unicode'` 指数部分使用 Unicode 表示 `1.23×10⁴⁵⁶`
|
|
1232
|
+
* - `'exp'` 用指数表示法, 用 `e` 替换 `×10` 部分 `1.23e+456`
|
|
1233
|
+
* - `'js'` 适合用于 JavaScript 的算式 `1.23*10**456`
|
|
1234
|
+
* - `'code'` 适合用于其他计算机语言的算式 `1.23*10^456`
|
|
1235
|
+
* - `'html'` 适合用于 HTML 展示的字符串 `1.23×10<sup>456</sup>`
|
|
1236
|
+
* - `'json'` 一个 JSON 字符串, 可以自由处理 `{"number":1.23,"exp":456}`
|
|
1237
|
+
*
|
|
1238
|
+
* `precision` 小数精度, 默认不作数值修约\
|
|
1239
|
+
* `round` 数值修约规则
|
|
1240
|
+
* - `'round'` 四舍五入
|
|
1241
|
+
* - `'banker'` 四舍六入五成双
|
|
1242
|
+
* - `'floor'` 向下取整
|
|
1243
|
+
* - `'ceil'` 向上取整
|
|
1244
|
+
* @returns 返回一个科学计数法表示的数字
|
|
1245
|
+
* @example
|
|
1246
|
+
* ```js
|
|
1247
|
+
* scientificNotation(1e12) // 1×10¹²
|
|
1248
|
+
* scientificNotation(-2.33e-8) // -2.33×10⁻⁸
|
|
1249
|
+
* // 可以指定输出类型
|
|
1250
|
+
* scientificNotation(1.234e-6, { type: 'exp' }) // 1.234e-6
|
|
1251
|
+
* scientificNotation(1.234e6, { type: 'exp' }) // 1.234e+6
|
|
1252
|
+
* scientificNotation(6.534e-6, { type: 'code' }) // 6.534*10^-6
|
|
1253
|
+
* scientificNotation(6.534e6, { type: 'code' }) // 6.534*10^6
|
|
1254
|
+
* scientificNotation(-4.321e-8, { type: 'html' }) // -4.321×10<sup>-8</sup>
|
|
1255
|
+
* scientificNotation(-4.321e8, { type: 'html' }) // -4.321×10<sup>8</sup>
|
|
1256
|
+
* scientificNotation(-9.87e-9, { type: 'json' }) // {"number":"-9.87","exp":-9}
|
|
1257
|
+
* scientificNotation(-9.87e9, { type: 'json' }) // {"number":"-9.87","exp":9}
|
|
1258
|
+
* // 可以指定小数点后的位数及数值修约规则
|
|
1259
|
+
* scientificNotation(1.235e6, { type: 'exp', precision: 2 }) // 1.24e+6
|
|
1260
|
+
* scientificNotation(6.545e-6, { type: 'code', precision: 2, round: 'banker' }) // 6.54*10^-6
|
|
1261
|
+
* scientificNotation(-9.87e9, { type: 'json', precision: 1, round: 'floor' }) // {"number":"-9.9","exp":9}
|
|
1262
|
+
* ```
|
|
1263
|
+
* @version 0.3.3
|
|
1264
|
+
*/
|
|
1265
|
+
declare function scientificNotation(num: string | number, options?: {
|
|
1266
|
+
type?: 'unicode' | 'exp' | 'js' | 'code' | 'html' | 'json';
|
|
1267
|
+
precision?: number;
|
|
1268
|
+
round?: 'round' | 'banker' | 'floor' | 'ceil';
|
|
1269
|
+
}): string;
|
|
1270
|
+
|
|
1109
1271
|
/**
|
|
1110
1272
|
* 根据文件名称判断是否匹配支持的文件类型,需要注意 `.C` 与 `.c` 的区别
|
|
1111
1273
|
* - `text/x-c++src` 对应 `.C`
|
|
@@ -1200,6 +1362,35 @@ declare function getAcceptableMIMEByExt(ext: string): string[];
|
|
|
1200
1362
|
*/
|
|
1201
1363
|
declare function randomChoice<T>(arr: ArrayLike<T>, weights?: ArrayLike<number>): T;
|
|
1202
1364
|
|
|
1365
|
+
/**
|
|
1366
|
+
* 一个广泛使用的[伪随机数生成算法(PRD)](https://github.com/Moushudyx/pseudo-random-distribution)\
|
|
1367
|
+
* 返回一个方法, 输出为布尔型, 可以生成一个比正常随机序列分布更加均匀的伪随机数列\
|
|
1368
|
+
* 可以极大地避免罕见牌型出现, 缺点是初始概率很低(即第一次命中的概率远远小于输入的 `p`)\
|
|
1369
|
+
* 建议在投入使用之前, 先调用 `ceil(1 / p)` 次作为初始化\
|
|
1370
|
+
* 此外需要注意的是, 这个算法的最终的精度并不是完全等于输入的 `p` 值
|
|
1371
|
+
* @param p 整体概率值, 即概率的数学期望
|
|
1372
|
+
* @param options 相关配置
|
|
1373
|
+
* - `threshold` 精度, 数值越小, 精度越高, 序列越接近目标 `p` 值, 默认为 `5e-6`
|
|
1374
|
+
* @returns 一个方法, 按给定的概率值返回 `true` 和 `false`
|
|
1375
|
+
* @example
|
|
1376
|
+
* ```js
|
|
1377
|
+
* const p0_5 = pipe(randomDistribution(0.5), Number)
|
|
1378
|
+
* p0_5() // 0, 1, 0, 0, 1, 1 ...
|
|
1379
|
+
* ```
|
|
1380
|
+
* @version 0.3.3
|
|
1381
|
+
*/
|
|
1382
|
+
declare function randomDistribution(p: number, options?: {
|
|
1383
|
+
threshold: number;
|
|
1384
|
+
}): () => boolean;
|
|
1385
|
+
/**
|
|
1386
|
+
* 内部方法, 用于实现 `randomDistribution` 中的 PRD 算法部分, 根据目标概率, 给出一个初始概率
|
|
1387
|
+
* @param targetP 目标概率
|
|
1388
|
+
* @param threshold 精度, 数值越小, 精度越高
|
|
1389
|
+
* @returns PRD 算法需要的初始概率
|
|
1390
|
+
* @version 0.3.3
|
|
1391
|
+
*/
|
|
1392
|
+
declare function getInitP(targetP: number, threshold?: number): number;
|
|
1393
|
+
|
|
1203
1394
|
/**
|
|
1204
1395
|
* 生成指定范围内的随机整数
|
|
1205
1396
|
* @param min 随机数的下界,包含于此范围内
|
|
@@ -2029,6 +2220,7 @@ declare function isEmpty(value: unknown): boolean;
|
|
|
2029
2220
|
* return fib(n - 1) + fib(n - 2)
|
|
2030
2221
|
* })
|
|
2031
2222
|
* ```
|
|
2223
|
+
* @version 0.2.1
|
|
2032
2224
|
*/
|
|
2033
2225
|
declare function memo<TArgs extends any[], TRes>(fn: (...args: TArgs) => TRes, options?: {
|
|
2034
2226
|
getKey?: (...args: TArgs) => string | number;
|
|
@@ -2216,5 +2408,5 @@ declare function throttle<T extends any[]>(fn: (...args: T) => any, delay: numbe
|
|
|
2216
2408
|
reset: () => void;
|
|
2217
2409
|
};
|
|
2218
2410
|
|
|
2219
|
-
export { $$Empty, _, acceptableFileName, acceptableFileType, camelCase, capitalize, cartesianProduct, caseCamel, caseConvert, caseKebab, casePascal, caseSnake, chunk, clamp, compose, _curryMore as curry, debounce, decimalNotation, dedent, deepClone, deepMerge, defer, fastClone, format, getAcceptableExtByMIME, getAcceptableMIMEByExt, getGlobalThis, getTag, indent, isArray, isArrayBuffer, isArrayLike, isBigInt, isBigInt64Array, isBigUint64Array, isBlob, isBoolean, isBuffer, isDataView, isDate, isEmpty, isEven, isFile, isFloat32Array, isFloat64Array, isFormData, isFunction, isInt16Array, isInt32Array, isInt8Array, isInteger, isIterable, isMap, isMergeEmptyPlaceholder, isNil, isNull, isNumber, isObject, isOdd, isPlaceholder, isPlainObject, isPrimitive, isPromise, isPromiseLike, isRegExp, isSet, isString, isSymbol, isTypedArray, isUint16Array, isUint32Array, isUint8Array, isUint8ClampedArray, isUndefined, isWeakMap, isWeakSet, isWrapperBigInt, isWrapperBoolean, isWrapperNumber, isWrapperObject, isWrapperString, isWrapperSymbol, kebabCase, memo, noop, not, parallel, pascalCase, pass, passWith, pipe, randomBase32String, randomChoice, randomHexString, randomInt, randomIntFloor, randomString, range, remove, retry, round, roundBank, roundBase, roundCeil, roundFloor, shuffle, sleep, snakeCase, splitWords, throttle, titleCase, tryit, ulid, uncapitalize, uuidNil, uuidV4, withResolvers };
|
|
2220
|
-
export type { BaseMargeType, Chunked, CloneOptions, CustomCloner, IsNegative, IsPositive, IsZero, MergeOption, MergeStrategy, MergeStrategyFunction, MergeType, MergeTypeStrategy, Not, RangeOptions, SourceMergeType, Stringify, TargetMergeType, TypedArray };
|
|
2411
|
+
export { $$Empty, _, acceptableFileName, acceptableFileType, camelCase, capitalize, cartesianProduct, caseCamel, caseConvert, caseKebab, casePascal, caseSnake, castArray, chunk, clamp, compose, _curryMore as curry, debounce, decimalNotation, dedent, deepClone, deepMerge, defer, fastClone, format, getAcceptableExtByMIME, getAcceptableMIMEByExt, getGlobalThis, getInitP, getTag, indent, isArray, isArrayBuffer, isArrayLike, isBigInt, isBigInt64Array, isBigUint64Array, isBlob, isBoolean, isBuffer, isDataView, isDate, isEmpty, isEven, isFile, isFloat32Array, isFloat64Array, isFormData, isFunction, isInt16Array, isInt32Array, isInt8Array, isInteger, isIterable, isMap, isMergeEmptyPlaceholder, isNil, isNull, isNumber, isObject, isOdd, isPlaceholder, isPlainObject, isPrimitive, isPromise, isPromiseLike, isRegExp, isSet, isString, isSymbol, isTypedArray, isUint16Array, isUint32Array, isUint8Array, isUint8ClampedArray, isUndefined, isWeakMap, isWeakSet, isWrapperBigInt, isWrapperBoolean, isWrapperNumber, isWrapperObject, isWrapperString, isWrapperSymbol, kebabCase, lerp, memo, noop, not, parallel, pascalCase, pass, passWith, pipe, randomBase32String, randomChoice, randomDistribution, randomHexString, randomInt, randomIntFloor, randomString, range, remove, retry, romanNumerals, round, roundBank, roundBase, roundCeil, roundFloor, scientificNotation, shuffle, sleep, snakeCase, splitWords, throttle, titleCase, tryit, ulid, uncapitalize, uuidNil, uuidV4, withResolvers };
|
|
2412
|
+
export type { BaseMargeType, CastArray, Chunked, CloneOptions, CustomCloner, IsNegative, IsPositive, IsZero, MergeOption, MergeStrategy, MergeStrategyFunction, MergeType, MergeTypeStrategy, Not, RangeOptions, SourceMergeType, Stringify, TargetMergeType, TypedArray };
|
package/lib/index.mjs
CHANGED
|
@@ -43,6 +43,10 @@ function cartesianProduct(...arrList) {
|
|
|
43
43
|
return res;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
function castArray(value) {
|
|
47
|
+
return Array.isArray(value) ? value.slice() : [value];
|
|
48
|
+
}
|
|
49
|
+
|
|
46
50
|
function chunk(array, size = 2) {
|
|
47
51
|
const res = [];
|
|
48
52
|
if (size < 1 || isNaN(size))
|
|
@@ -607,6 +611,201 @@ function format(num, options) {
|
|
|
607
611
|
return sign + integer;
|
|
608
612
|
}
|
|
609
613
|
|
|
614
|
+
function lerp(val1, val2, t) {
|
|
615
|
+
if (isNumber(val1)) {
|
|
616
|
+
if (!isNumber(val2))
|
|
617
|
+
throw new Error('Invalid val2 parameter: val2 should be a number');
|
|
618
|
+
return _lerp(val1, val2, t);
|
|
619
|
+
}
|
|
620
|
+
else if (isArray(val1)) {
|
|
621
|
+
if (!isArray(val2))
|
|
622
|
+
throw new Error('Invalid val2 parameter: val2 should be an Array');
|
|
623
|
+
if (val1.length !== val2.length) {
|
|
624
|
+
throw new Error(`Invalid val2 parameter: the length of val2 (${val2.length}) should be consistent with val1 (${val1.length})`);
|
|
625
|
+
}
|
|
626
|
+
if (val1.length === 0)
|
|
627
|
+
return [];
|
|
628
|
+
if (isNumber(val1[0])) {
|
|
629
|
+
if (!isNumber(val2[0]))
|
|
630
|
+
throw new Error('Invalid val2 parameter: val2 should be an Array<number>');
|
|
631
|
+
return val1.map((v1, index) => _lerp(v1, val2[index], t));
|
|
632
|
+
}
|
|
633
|
+
else if (isArray(val1[0])) {
|
|
634
|
+
const res = [];
|
|
635
|
+
for (let i = 0; i < val1.length; i++) {
|
|
636
|
+
const arr1 = val1[i];
|
|
637
|
+
const arr2 = val2[i];
|
|
638
|
+
if (arr1.length !== arr2.length) {
|
|
639
|
+
throw new Error(`Invalid val2 parameter: The length of array at index ${i} in val2 (${arr2.length}) must match the length of the corresponding array in val1 (${arr1.length})`);
|
|
640
|
+
}
|
|
641
|
+
res.push(arr1.map((v1, index) => _lerp(v1, arr2[index], t)));
|
|
642
|
+
}
|
|
643
|
+
return res;
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
throw new Error('Invalid val1 parameter: val1 should be a number or Array');
|
|
647
|
+
}
|
|
648
|
+
function _lerp(val1, val2, t) {
|
|
649
|
+
return val1 + (val2 - val1) * t;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
function romanNumerals(num, options) {
|
|
653
|
+
const str = decimalNotation(num);
|
|
654
|
+
if (/NaN|Inf/.test(str))
|
|
655
|
+
return str;
|
|
656
|
+
const type = (options || {}).type || 'unicode';
|
|
657
|
+
const thousand = (options || {}).thousand || 'normal';
|
|
658
|
+
const forceSplitThousand = thousand === 'strict';
|
|
659
|
+
const integer = str.split('.')[0].replace('-', '');
|
|
660
|
+
if (integer === '0') {
|
|
661
|
+
const zero = (options || {}).zero || '0';
|
|
662
|
+
if (type === 'json')
|
|
663
|
+
return `["${zero}"]`;
|
|
664
|
+
else
|
|
665
|
+
return zero;
|
|
666
|
+
}
|
|
667
|
+
if (integer === '1') {
|
|
668
|
+
const one = (options || {}).one || 'I';
|
|
669
|
+
if (type === 'json')
|
|
670
|
+
return `["${one}"]`;
|
|
671
|
+
else
|
|
672
|
+
return one;
|
|
673
|
+
}
|
|
674
|
+
const chunks = chunk(Array.from(integer).reverse(), 3);
|
|
675
|
+
const romanChunks = [];
|
|
676
|
+
for (let i = 0; i < chunks.length; i++) {
|
|
677
|
+
const val = Number(chunks[i].reverse().join(''));
|
|
678
|
+
if (i === chunks.length - 2 && !forceSplitThousand && Number(chunks[i + 1]) < 4) {
|
|
679
|
+
romanChunks.push(number2roman(val + Number(chunks[i + 1]) * 1000));
|
|
680
|
+
break;
|
|
681
|
+
}
|
|
682
|
+
else {
|
|
683
|
+
romanChunks.push(number2roman(val));
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
switch (type) {
|
|
687
|
+
case 'js':
|
|
688
|
+
return romanChunks
|
|
689
|
+
.map((str, index) => str
|
|
690
|
+
.split('')
|
|
691
|
+
.map((s) => s + '\\\\u0305'.repeat(index))
|
|
692
|
+
.join(''))
|
|
693
|
+
.reverse()
|
|
694
|
+
.join('');
|
|
695
|
+
case 'html':
|
|
696
|
+
return romanChunks
|
|
697
|
+
.map((str, index) => str
|
|
698
|
+
.split('')
|
|
699
|
+
.map((s) => s + '̅'.repeat(index))
|
|
700
|
+
.join(''))
|
|
701
|
+
.reverse()
|
|
702
|
+
.join('');
|
|
703
|
+
case 'json':
|
|
704
|
+
return `[${romanChunks.map((str) => `"${str}"`).join(', ')}]`;
|
|
705
|
+
case 'unicode':
|
|
706
|
+
default:
|
|
707
|
+
return romanChunks
|
|
708
|
+
.map((str, index) => str
|
|
709
|
+
.split('')
|
|
710
|
+
.map((s) => s + '\u0305'.repeat(index))
|
|
711
|
+
.join(''))
|
|
712
|
+
.reverse()
|
|
713
|
+
.join('');
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
function number2roman(num) {
|
|
717
|
+
const symbols = [
|
|
718
|
+
[1000, 'M'],
|
|
719
|
+
[900, 'CM'],
|
|
720
|
+
[500, 'D'],
|
|
721
|
+
[400, 'CD'],
|
|
722
|
+
[100, 'C'],
|
|
723
|
+
[90, 'XC'],
|
|
724
|
+
[50, 'L'],
|
|
725
|
+
[40, 'XL'],
|
|
726
|
+
[10, 'X'],
|
|
727
|
+
[9, 'IX'],
|
|
728
|
+
[5, 'V'],
|
|
729
|
+
[4, 'IV'],
|
|
730
|
+
[1, 'I'],
|
|
731
|
+
];
|
|
732
|
+
let roman = '';
|
|
733
|
+
for (const [val, str] of symbols) {
|
|
734
|
+
while (num >= val) {
|
|
735
|
+
num -= val;
|
|
736
|
+
roman += str;
|
|
737
|
+
}
|
|
738
|
+
if (num == 0)
|
|
739
|
+
break;
|
|
740
|
+
}
|
|
741
|
+
return roman;
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
function scientificNotation(num, options) {
|
|
745
|
+
const str = decimalNotation(num);
|
|
746
|
+
if (/NaN|Inf/.test(str))
|
|
747
|
+
return str;
|
|
748
|
+
const type = (options || {}).type || 'unicode';
|
|
749
|
+
const _precision = (options || {}).precision;
|
|
750
|
+
const precision = isNumber(_precision) ? clamp(_precision !== null && _precision !== void 0 ? _precision : 2, 0, Infinity) : null;
|
|
751
|
+
const round = (options || {}).round || 'round';
|
|
752
|
+
let [integer, fractional] = str.split('.');
|
|
753
|
+
let sign = '';
|
|
754
|
+
if (/^-/.test(integer)) {
|
|
755
|
+
integer = integer.substring(1);
|
|
756
|
+
sign = '-';
|
|
757
|
+
}
|
|
758
|
+
fractional = fractional !== null && fractional !== void 0 ? fractional : '';
|
|
759
|
+
let exp = 0;
|
|
760
|
+
let n = '';
|
|
761
|
+
if (integer === '0') {
|
|
762
|
+
exp = /^(0+)/.test(fractional) ? -(fractional.match(/^(0+)/)[0].length + 1) : -1;
|
|
763
|
+
[integer, fractional] = [fractional.slice(-exp - 1, -exp), fractional.slice(-exp)];
|
|
764
|
+
}
|
|
765
|
+
else {
|
|
766
|
+
exp = integer.length - 1;
|
|
767
|
+
[integer, fractional] = [integer.slice(0, 1), integer.slice(1) + fractional];
|
|
768
|
+
}
|
|
769
|
+
if (isNumber(precision)) {
|
|
770
|
+
if (fractional.length > precision) {
|
|
771
|
+
const roundMap = { round: roundBase, banker: roundBank, floor: roundFloor, ceil: roundCeil };
|
|
772
|
+
[integer, fractional] = (roundMap[round] || roundBase)(integer, fractional, precision, !!sign);
|
|
773
|
+
}
|
|
774
|
+
else if (fractional.length < precision) {
|
|
775
|
+
fractional += '0'.repeat(precision - fractional.length);
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
else {
|
|
779
|
+
fractional = fractional.replace(/0+$/, '');
|
|
780
|
+
}
|
|
781
|
+
if ((precision === null && fractional) || (isNumber(precision) && precision > 0)) {
|
|
782
|
+
n = sign + integer + '.' + fractional;
|
|
783
|
+
}
|
|
784
|
+
else
|
|
785
|
+
n = sign + integer;
|
|
786
|
+
switch (type) {
|
|
787
|
+
case 'exp':
|
|
788
|
+
return `${n}e${exp < 0 ? '' : '+'}${exp}`;
|
|
789
|
+
case 'js':
|
|
790
|
+
return `${n}*10**${exp}`;
|
|
791
|
+
case 'code':
|
|
792
|
+
return `${n}*10^${exp}`;
|
|
793
|
+
case 'html':
|
|
794
|
+
return `${n}×10<sup>${exp}</sup>`;
|
|
795
|
+
case 'json':
|
|
796
|
+
return `{"number":"${n}","exp":${exp}}`;
|
|
797
|
+
case 'unicode':
|
|
798
|
+
default:
|
|
799
|
+
return `${n}×10${transferNumberToUniCode(String(exp))}`;
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
function transferNumberToUniCode(n) {
|
|
803
|
+
const strMap = Object.assign(Object.assign({}, Array.from('⁰¹²³⁴⁵⁶⁷⁸⁹')), { '-': '⁻', '+': '⁺' });
|
|
804
|
+
return Array.from(n)
|
|
805
|
+
.map((s) => (strMap[s] ? strMap[s] : s))
|
|
806
|
+
.join('');
|
|
807
|
+
}
|
|
808
|
+
|
|
610
809
|
function parallel(args, fn, options) {
|
|
611
810
|
return __awaiter(this, void 0, void 0, function* () {
|
|
612
811
|
if (!args.length)
|
|
@@ -1238,6 +1437,54 @@ function randomChoice(arr, weights) {
|
|
|
1238
1437
|
return arr[index];
|
|
1239
1438
|
}
|
|
1240
1439
|
|
|
1440
|
+
function randomDistribution(p, options) {
|
|
1441
|
+
const threshold = (options === null || options === void 0 ? void 0 : options.threshold) ? Math.max(options.threshold, Number.MIN_VALUE * 2) : 5e-6;
|
|
1442
|
+
const C = getInitP(p, threshold);
|
|
1443
|
+
let current = C;
|
|
1444
|
+
return function getRandomDistribution() {
|
|
1445
|
+
const res = Math.random() < current;
|
|
1446
|
+
if (res)
|
|
1447
|
+
current = C;
|
|
1448
|
+
else
|
|
1449
|
+
current += C;
|
|
1450
|
+
return res;
|
|
1451
|
+
};
|
|
1452
|
+
}
|
|
1453
|
+
function getInitP(targetP, threshold = 5e-6) {
|
|
1454
|
+
if (targetP <= 0)
|
|
1455
|
+
return 0;
|
|
1456
|
+
if (targetP >= 1)
|
|
1457
|
+
return 1;
|
|
1458
|
+
let [down, up] = [0, 1];
|
|
1459
|
+
let mid = 1;
|
|
1460
|
+
let tempP = 1;
|
|
1461
|
+
let tempPLast = 1;
|
|
1462
|
+
let step = 64;
|
|
1463
|
+
while (step-- > 0) {
|
|
1464
|
+
mid = (down + up) / 2;
|
|
1465
|
+
tempP = getRealPFromInitP(mid);
|
|
1466
|
+
if (Math.abs(tempPLast - tempP) < threshold)
|
|
1467
|
+
break;
|
|
1468
|
+
if (tempP > targetP)
|
|
1469
|
+
up = mid;
|
|
1470
|
+
else
|
|
1471
|
+
down = mid;
|
|
1472
|
+
}
|
|
1473
|
+
return mid;
|
|
1474
|
+
}
|
|
1475
|
+
function getRealPFromInitP(initP) {
|
|
1476
|
+
let sum = 0;
|
|
1477
|
+
let prod = 0;
|
|
1478
|
+
let cur = 0;
|
|
1479
|
+
let max = Math.ceil(1 / initP);
|
|
1480
|
+
for (let n = 1; n <= max; n++) {
|
|
1481
|
+
cur = Math.min(1, n * initP) * (1 - prod);
|
|
1482
|
+
prod += cur;
|
|
1483
|
+
sum += n * cur;
|
|
1484
|
+
}
|
|
1485
|
+
return 1 / sum;
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1241
1488
|
const radix32 = '0123456789abcdefghijklmnopqrstuv';
|
|
1242
1489
|
const base32Chars = 'abcdefghijklmnopqrstuvwxyz234567';
|
|
1243
1490
|
const base32Crockford = '0123456789abcdefghjkmnpqrstvwxyz';
|
|
@@ -1864,22 +2111,22 @@ function _deepClone(obj, map, options) {
|
|
|
1864
2111
|
if (isFormData(obj))
|
|
1865
2112
|
return _cloneFormData(obj, map, _deepClone, options);
|
|
1866
2113
|
let res;
|
|
1867
|
-
if (obj
|
|
2114
|
+
if (isDate(obj)) {
|
|
1868
2115
|
res = new Date(obj.valueOf());
|
|
1869
2116
|
map.set(obj, res);
|
|
1870
2117
|
}
|
|
1871
|
-
else if (obj
|
|
2118
|
+
else if (isRegExp(obj)) {
|
|
1872
2119
|
res = new RegExp(obj.source, obj.flags);
|
|
1873
2120
|
map.set(obj, res);
|
|
1874
2121
|
}
|
|
1875
|
-
else if (obj
|
|
2122
|
+
else if (isArrayBuffer(obj)) {
|
|
1876
2123
|
res = _cloneArrayBuffer(obj, map);
|
|
1877
2124
|
}
|
|
1878
2125
|
else if (isTypedArray(obj)) {
|
|
1879
2126
|
res = new obj.constructor(_cloneArrayBuffer(obj.buffer, map), obj.byteOffset, obj.length);
|
|
1880
2127
|
map.set(obj, res);
|
|
1881
2128
|
}
|
|
1882
|
-
else if (obj
|
|
2129
|
+
else if (isDataView(obj)) {
|
|
1883
2130
|
res = new DataView(map.has(obj.buffer) ? map.get(obj.buffer) : _cloneArrayBuffer(obj.buffer, map), obj.byteOffset, obj.byteLength);
|
|
1884
2131
|
map.set(obj, res);
|
|
1885
2132
|
}
|
|
@@ -2275,4 +2522,4 @@ function throttle(fn, delay, options) {
|
|
|
2275
2522
|
return _throttle(fn, delay, Object.assign({ trailing: false, leading: true }, options));
|
|
2276
2523
|
}
|
|
2277
2524
|
|
|
2278
|
-
export { $$Empty, _, acceptableFileName, acceptableFileType, camelCase, capitalize, cartesianProduct, caseCamel, caseConvert, caseKebab, casePascal, caseSnake, chunk, clamp, compose, _curryMore as curry, debounce, decimalNotation, dedent, deepClone, deepMerge, defer, fastClone, format, getAcceptableExtByMIME, getAcceptableMIMEByExt, getGlobalThis, getTag, indent, isArray, isArrayBuffer, isArrayLike, isBigInt, isBigInt64Array, isBigUint64Array, isBlob, isBoolean, isBuffer, isDataView, isDate, isEmpty, isEven, isFile, isFloat32Array, isFloat64Array, isFormData, isFunction, isInt16Array, isInt32Array, isInt8Array, isInteger, isIterable, isMap, isMergeEmptyPlaceholder, isNil, isNull, isNumber, isObject, isOdd, isPlaceholder, isPlainObject, isPrimitive, isPromise, isPromiseLike, isRegExp, isSet, isString, isSymbol, isTypedArray, isUint16Array, isUint32Array, isUint8Array, isUint8ClampedArray, isUndefined, isWeakMap, isWeakSet, isWrapperBigInt, isWrapperBoolean, isWrapperNumber, isWrapperObject, isWrapperString, isWrapperSymbol, kebabCase, memo, noop, not, parallel, pascalCase, pass, passWith, pipe, randomBase32String, randomChoice, randomHexString, randomInt, randomIntFloor, randomString, range, remove, retry, round, roundBank, roundBase, roundCeil, roundFloor, shuffle, sleep, snakeCase, splitWords, throttle, titleCase, tryit, ulid, uncapitalize, uuidNil, uuidV4, withResolvers };
|
|
2525
|
+
export { $$Empty, _, acceptableFileName, acceptableFileType, camelCase, capitalize, cartesianProduct, caseCamel, caseConvert, caseKebab, casePascal, caseSnake, castArray, chunk, clamp, compose, _curryMore as curry, debounce, decimalNotation, dedent, deepClone, deepMerge, defer, fastClone, format, getAcceptableExtByMIME, getAcceptableMIMEByExt, getGlobalThis, getInitP, getTag, indent, isArray, isArrayBuffer, isArrayLike, isBigInt, isBigInt64Array, isBigUint64Array, isBlob, isBoolean, isBuffer, isDataView, isDate, isEmpty, isEven, isFile, isFloat32Array, isFloat64Array, isFormData, isFunction, isInt16Array, isInt32Array, isInt8Array, isInteger, isIterable, isMap, isMergeEmptyPlaceholder, isNil, isNull, isNumber, isObject, isOdd, isPlaceholder, isPlainObject, isPrimitive, isPromise, isPromiseLike, isRegExp, isSet, isString, isSymbol, isTypedArray, isUint16Array, isUint32Array, isUint8Array, isUint8ClampedArray, isUndefined, isWeakMap, isWeakSet, isWrapperBigInt, isWrapperBoolean, isWrapperNumber, isWrapperObject, isWrapperString, isWrapperSymbol, kebabCase, lerp, memo, noop, not, parallel, pascalCase, pass, passWith, pipe, randomBase32String, randomChoice, randomDistribution, randomHexString, randomInt, randomIntFloor, randomString, range, remove, retry, romanNumerals, round, roundBank, roundBase, roundCeil, roundFloor, scientificNotation, shuffle, sleep, snakeCase, splitWords, throttle, titleCase, tryit, ulid, uncapitalize, uuidNil, uuidV4, withResolvers };
|
package/lib/index.umd.js
CHANGED
|
@@ -49,6 +49,10 @@ See the Mulan PSL v2 for more details.
|
|
|
49
49
|
return res;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
function castArray(value) {
|
|
53
|
+
return Array.isArray(value) ? value.slice() : [value];
|
|
54
|
+
}
|
|
55
|
+
|
|
52
56
|
function chunk(array, size = 2) {
|
|
53
57
|
const res = [];
|
|
54
58
|
if (size < 1 || isNaN(size))
|
|
@@ -613,6 +617,201 @@ See the Mulan PSL v2 for more details.
|
|
|
613
617
|
return sign + integer;
|
|
614
618
|
}
|
|
615
619
|
|
|
620
|
+
function lerp(val1, val2, t) {
|
|
621
|
+
if (isNumber(val1)) {
|
|
622
|
+
if (!isNumber(val2))
|
|
623
|
+
throw new Error('Invalid val2 parameter: val2 should be a number');
|
|
624
|
+
return _lerp(val1, val2, t);
|
|
625
|
+
}
|
|
626
|
+
else if (isArray(val1)) {
|
|
627
|
+
if (!isArray(val2))
|
|
628
|
+
throw new Error('Invalid val2 parameter: val2 should be an Array');
|
|
629
|
+
if (val1.length !== val2.length) {
|
|
630
|
+
throw new Error(`Invalid val2 parameter: the length of val2 (${val2.length}) should be consistent with val1 (${val1.length})`);
|
|
631
|
+
}
|
|
632
|
+
if (val1.length === 0)
|
|
633
|
+
return [];
|
|
634
|
+
if (isNumber(val1[0])) {
|
|
635
|
+
if (!isNumber(val2[0]))
|
|
636
|
+
throw new Error('Invalid val2 parameter: val2 should be an Array<number>');
|
|
637
|
+
return val1.map((v1, index) => _lerp(v1, val2[index], t));
|
|
638
|
+
}
|
|
639
|
+
else if (isArray(val1[0])) {
|
|
640
|
+
const res = [];
|
|
641
|
+
for (let i = 0; i < val1.length; i++) {
|
|
642
|
+
const arr1 = val1[i];
|
|
643
|
+
const arr2 = val2[i];
|
|
644
|
+
if (arr1.length !== arr2.length) {
|
|
645
|
+
throw new Error(`Invalid val2 parameter: The length of array at index ${i} in val2 (${arr2.length}) must match the length of the corresponding array in val1 (${arr1.length})`);
|
|
646
|
+
}
|
|
647
|
+
res.push(arr1.map((v1, index) => _lerp(v1, arr2[index], t)));
|
|
648
|
+
}
|
|
649
|
+
return res;
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
throw new Error('Invalid val1 parameter: val1 should be a number or Array');
|
|
653
|
+
}
|
|
654
|
+
function _lerp(val1, val2, t) {
|
|
655
|
+
return val1 + (val2 - val1) * t;
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
function romanNumerals(num, options) {
|
|
659
|
+
const str = decimalNotation(num);
|
|
660
|
+
if (/NaN|Inf/.test(str))
|
|
661
|
+
return str;
|
|
662
|
+
const type = (options || {}).type || 'unicode';
|
|
663
|
+
const thousand = (options || {}).thousand || 'normal';
|
|
664
|
+
const forceSplitThousand = thousand === 'strict';
|
|
665
|
+
const integer = str.split('.')[0].replace('-', '');
|
|
666
|
+
if (integer === '0') {
|
|
667
|
+
const zero = (options || {}).zero || '0';
|
|
668
|
+
if (type === 'json')
|
|
669
|
+
return `["${zero}"]`;
|
|
670
|
+
else
|
|
671
|
+
return zero;
|
|
672
|
+
}
|
|
673
|
+
if (integer === '1') {
|
|
674
|
+
const one = (options || {}).one || 'I';
|
|
675
|
+
if (type === 'json')
|
|
676
|
+
return `["${one}"]`;
|
|
677
|
+
else
|
|
678
|
+
return one;
|
|
679
|
+
}
|
|
680
|
+
const chunks = chunk(Array.from(integer).reverse(), 3);
|
|
681
|
+
const romanChunks = [];
|
|
682
|
+
for (let i = 0; i < chunks.length; i++) {
|
|
683
|
+
const val = Number(chunks[i].reverse().join(''));
|
|
684
|
+
if (i === chunks.length - 2 && !forceSplitThousand && Number(chunks[i + 1]) < 4) {
|
|
685
|
+
romanChunks.push(number2roman(val + Number(chunks[i + 1]) * 1000));
|
|
686
|
+
break;
|
|
687
|
+
}
|
|
688
|
+
else {
|
|
689
|
+
romanChunks.push(number2roman(val));
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
switch (type) {
|
|
693
|
+
case 'js':
|
|
694
|
+
return romanChunks
|
|
695
|
+
.map((str, index) => str
|
|
696
|
+
.split('')
|
|
697
|
+
.map((s) => s + '\\\\u0305'.repeat(index))
|
|
698
|
+
.join(''))
|
|
699
|
+
.reverse()
|
|
700
|
+
.join('');
|
|
701
|
+
case 'html':
|
|
702
|
+
return romanChunks
|
|
703
|
+
.map((str, index) => str
|
|
704
|
+
.split('')
|
|
705
|
+
.map((s) => s + '̅'.repeat(index))
|
|
706
|
+
.join(''))
|
|
707
|
+
.reverse()
|
|
708
|
+
.join('');
|
|
709
|
+
case 'json':
|
|
710
|
+
return `[${romanChunks.map((str) => `"${str}"`).join(', ')}]`;
|
|
711
|
+
case 'unicode':
|
|
712
|
+
default:
|
|
713
|
+
return romanChunks
|
|
714
|
+
.map((str, index) => str
|
|
715
|
+
.split('')
|
|
716
|
+
.map((s) => s + '\u0305'.repeat(index))
|
|
717
|
+
.join(''))
|
|
718
|
+
.reverse()
|
|
719
|
+
.join('');
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
function number2roman(num) {
|
|
723
|
+
const symbols = [
|
|
724
|
+
[1000, 'M'],
|
|
725
|
+
[900, 'CM'],
|
|
726
|
+
[500, 'D'],
|
|
727
|
+
[400, 'CD'],
|
|
728
|
+
[100, 'C'],
|
|
729
|
+
[90, 'XC'],
|
|
730
|
+
[50, 'L'],
|
|
731
|
+
[40, 'XL'],
|
|
732
|
+
[10, 'X'],
|
|
733
|
+
[9, 'IX'],
|
|
734
|
+
[5, 'V'],
|
|
735
|
+
[4, 'IV'],
|
|
736
|
+
[1, 'I'],
|
|
737
|
+
];
|
|
738
|
+
let roman = '';
|
|
739
|
+
for (const [val, str] of symbols) {
|
|
740
|
+
while (num >= val) {
|
|
741
|
+
num -= val;
|
|
742
|
+
roman += str;
|
|
743
|
+
}
|
|
744
|
+
if (num == 0)
|
|
745
|
+
break;
|
|
746
|
+
}
|
|
747
|
+
return roman;
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
function scientificNotation(num, options) {
|
|
751
|
+
const str = decimalNotation(num);
|
|
752
|
+
if (/NaN|Inf/.test(str))
|
|
753
|
+
return str;
|
|
754
|
+
const type = (options || {}).type || 'unicode';
|
|
755
|
+
const _precision = (options || {}).precision;
|
|
756
|
+
const precision = isNumber(_precision) ? clamp(_precision !== null && _precision !== void 0 ? _precision : 2, 0, Infinity) : null;
|
|
757
|
+
const round = (options || {}).round || 'round';
|
|
758
|
+
let [integer, fractional] = str.split('.');
|
|
759
|
+
let sign = '';
|
|
760
|
+
if (/^-/.test(integer)) {
|
|
761
|
+
integer = integer.substring(1);
|
|
762
|
+
sign = '-';
|
|
763
|
+
}
|
|
764
|
+
fractional = fractional !== null && fractional !== void 0 ? fractional : '';
|
|
765
|
+
let exp = 0;
|
|
766
|
+
let n = '';
|
|
767
|
+
if (integer === '0') {
|
|
768
|
+
exp = /^(0+)/.test(fractional) ? -(fractional.match(/^(0+)/)[0].length + 1) : -1;
|
|
769
|
+
[integer, fractional] = [fractional.slice(-exp - 1, -exp), fractional.slice(-exp)];
|
|
770
|
+
}
|
|
771
|
+
else {
|
|
772
|
+
exp = integer.length - 1;
|
|
773
|
+
[integer, fractional] = [integer.slice(0, 1), integer.slice(1) + fractional];
|
|
774
|
+
}
|
|
775
|
+
if (isNumber(precision)) {
|
|
776
|
+
if (fractional.length > precision) {
|
|
777
|
+
const roundMap = { round: roundBase, banker: roundBank, floor: roundFloor, ceil: roundCeil };
|
|
778
|
+
[integer, fractional] = (roundMap[round] || roundBase)(integer, fractional, precision, !!sign);
|
|
779
|
+
}
|
|
780
|
+
else if (fractional.length < precision) {
|
|
781
|
+
fractional += '0'.repeat(precision - fractional.length);
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
else {
|
|
785
|
+
fractional = fractional.replace(/0+$/, '');
|
|
786
|
+
}
|
|
787
|
+
if ((precision === null && fractional) || (isNumber(precision) && precision > 0)) {
|
|
788
|
+
n = sign + integer + '.' + fractional;
|
|
789
|
+
}
|
|
790
|
+
else
|
|
791
|
+
n = sign + integer;
|
|
792
|
+
switch (type) {
|
|
793
|
+
case 'exp':
|
|
794
|
+
return `${n}e${exp < 0 ? '' : '+'}${exp}`;
|
|
795
|
+
case 'js':
|
|
796
|
+
return `${n}*10**${exp}`;
|
|
797
|
+
case 'code':
|
|
798
|
+
return `${n}*10^${exp}`;
|
|
799
|
+
case 'html':
|
|
800
|
+
return `${n}×10<sup>${exp}</sup>`;
|
|
801
|
+
case 'json':
|
|
802
|
+
return `{"number":"${n}","exp":${exp}}`;
|
|
803
|
+
case 'unicode':
|
|
804
|
+
default:
|
|
805
|
+
return `${n}×10${transferNumberToUniCode(String(exp))}`;
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
function transferNumberToUniCode(n) {
|
|
809
|
+
const strMap = Object.assign(Object.assign({}, Array.from('⁰¹²³⁴⁵⁶⁷⁸⁹')), { '-': '⁻', '+': '⁺' });
|
|
810
|
+
return Array.from(n)
|
|
811
|
+
.map((s) => (strMap[s] ? strMap[s] : s))
|
|
812
|
+
.join('');
|
|
813
|
+
}
|
|
814
|
+
|
|
616
815
|
function parallel(args, fn, options) {
|
|
617
816
|
return __awaiter(this, void 0, void 0, function* () {
|
|
618
817
|
if (!args.length)
|
|
@@ -1244,6 +1443,54 @@ See the Mulan PSL v2 for more details.
|
|
|
1244
1443
|
return arr[index];
|
|
1245
1444
|
}
|
|
1246
1445
|
|
|
1446
|
+
function randomDistribution(p, options) {
|
|
1447
|
+
const threshold = (options === null || options === void 0 ? void 0 : options.threshold) ? Math.max(options.threshold, Number.MIN_VALUE * 2) : 5e-6;
|
|
1448
|
+
const C = getInitP(p, threshold);
|
|
1449
|
+
let current = C;
|
|
1450
|
+
return function getRandomDistribution() {
|
|
1451
|
+
const res = Math.random() < current;
|
|
1452
|
+
if (res)
|
|
1453
|
+
current = C;
|
|
1454
|
+
else
|
|
1455
|
+
current += C;
|
|
1456
|
+
return res;
|
|
1457
|
+
};
|
|
1458
|
+
}
|
|
1459
|
+
function getInitP(targetP, threshold = 5e-6) {
|
|
1460
|
+
if (targetP <= 0)
|
|
1461
|
+
return 0;
|
|
1462
|
+
if (targetP >= 1)
|
|
1463
|
+
return 1;
|
|
1464
|
+
let [down, up] = [0, 1];
|
|
1465
|
+
let mid = 1;
|
|
1466
|
+
let tempP = 1;
|
|
1467
|
+
let tempPLast = 1;
|
|
1468
|
+
let step = 64;
|
|
1469
|
+
while (step-- > 0) {
|
|
1470
|
+
mid = (down + up) / 2;
|
|
1471
|
+
tempP = getRealPFromInitP(mid);
|
|
1472
|
+
if (Math.abs(tempPLast - tempP) < threshold)
|
|
1473
|
+
break;
|
|
1474
|
+
if (tempP > targetP)
|
|
1475
|
+
up = mid;
|
|
1476
|
+
else
|
|
1477
|
+
down = mid;
|
|
1478
|
+
}
|
|
1479
|
+
return mid;
|
|
1480
|
+
}
|
|
1481
|
+
function getRealPFromInitP(initP) {
|
|
1482
|
+
let sum = 0;
|
|
1483
|
+
let prod = 0;
|
|
1484
|
+
let cur = 0;
|
|
1485
|
+
let max = Math.ceil(1 / initP);
|
|
1486
|
+
for (let n = 1; n <= max; n++) {
|
|
1487
|
+
cur = Math.min(1, n * initP) * (1 - prod);
|
|
1488
|
+
prod += cur;
|
|
1489
|
+
sum += n * cur;
|
|
1490
|
+
}
|
|
1491
|
+
return 1 / sum;
|
|
1492
|
+
}
|
|
1493
|
+
|
|
1247
1494
|
const radix32 = '0123456789abcdefghijklmnopqrstuv';
|
|
1248
1495
|
const base32Chars = 'abcdefghijklmnopqrstuvwxyz234567';
|
|
1249
1496
|
const base32Crockford = '0123456789abcdefghjkmnpqrstvwxyz';
|
|
@@ -1870,22 +2117,22 @@ See the Mulan PSL v2 for more details.
|
|
|
1870
2117
|
if (isFormData(obj))
|
|
1871
2118
|
return _cloneFormData(obj, map, _deepClone, options);
|
|
1872
2119
|
let res;
|
|
1873
|
-
if (obj
|
|
2120
|
+
if (isDate(obj)) {
|
|
1874
2121
|
res = new Date(obj.valueOf());
|
|
1875
2122
|
map.set(obj, res);
|
|
1876
2123
|
}
|
|
1877
|
-
else if (obj
|
|
2124
|
+
else if (isRegExp(obj)) {
|
|
1878
2125
|
res = new RegExp(obj.source, obj.flags);
|
|
1879
2126
|
map.set(obj, res);
|
|
1880
2127
|
}
|
|
1881
|
-
else if (obj
|
|
2128
|
+
else if (isArrayBuffer(obj)) {
|
|
1882
2129
|
res = _cloneArrayBuffer(obj, map);
|
|
1883
2130
|
}
|
|
1884
2131
|
else if (isTypedArray(obj)) {
|
|
1885
2132
|
res = new obj.constructor(_cloneArrayBuffer(obj.buffer, map), obj.byteOffset, obj.length);
|
|
1886
2133
|
map.set(obj, res);
|
|
1887
2134
|
}
|
|
1888
|
-
else if (obj
|
|
2135
|
+
else if (isDataView(obj)) {
|
|
1889
2136
|
res = new DataView(map.has(obj.buffer) ? map.get(obj.buffer) : _cloneArrayBuffer(obj.buffer, map), obj.byteOffset, obj.byteLength);
|
|
1890
2137
|
map.set(obj, res);
|
|
1891
2138
|
}
|
|
@@ -2293,6 +2540,7 @@ See the Mulan PSL v2 for more details.
|
|
|
2293
2540
|
exports.caseKebab = caseKebab;
|
|
2294
2541
|
exports.casePascal = casePascal;
|
|
2295
2542
|
exports.caseSnake = caseSnake;
|
|
2543
|
+
exports.castArray = castArray;
|
|
2296
2544
|
exports.chunk = chunk;
|
|
2297
2545
|
exports.clamp = clamp;
|
|
2298
2546
|
exports.compose = compose;
|
|
@@ -2308,6 +2556,7 @@ See the Mulan PSL v2 for more details.
|
|
|
2308
2556
|
exports.getAcceptableExtByMIME = getAcceptableExtByMIME;
|
|
2309
2557
|
exports.getAcceptableMIMEByExt = getAcceptableMIMEByExt;
|
|
2310
2558
|
exports.getGlobalThis = getGlobalThis;
|
|
2559
|
+
exports.getInitP = getInitP;
|
|
2311
2560
|
exports.getTag = getTag;
|
|
2312
2561
|
exports.indent = indent;
|
|
2313
2562
|
exports.isArray = isArray;
|
|
@@ -2364,6 +2613,7 @@ See the Mulan PSL v2 for more details.
|
|
|
2364
2613
|
exports.isWrapperString = isWrapperString;
|
|
2365
2614
|
exports.isWrapperSymbol = isWrapperSymbol;
|
|
2366
2615
|
exports.kebabCase = kebabCase;
|
|
2616
|
+
exports.lerp = lerp;
|
|
2367
2617
|
exports.memo = memo;
|
|
2368
2618
|
exports.noop = noop;
|
|
2369
2619
|
exports.not = not;
|
|
@@ -2374,6 +2624,7 @@ See the Mulan PSL v2 for more details.
|
|
|
2374
2624
|
exports.pipe = pipe;
|
|
2375
2625
|
exports.randomBase32String = randomBase32String;
|
|
2376
2626
|
exports.randomChoice = randomChoice;
|
|
2627
|
+
exports.randomDistribution = randomDistribution;
|
|
2377
2628
|
exports.randomHexString = randomHexString;
|
|
2378
2629
|
exports.randomInt = randomInt;
|
|
2379
2630
|
exports.randomIntFloor = randomIntFloor;
|
|
@@ -2381,11 +2632,13 @@ See the Mulan PSL v2 for more details.
|
|
|
2381
2632
|
exports.range = range;
|
|
2382
2633
|
exports.remove = remove;
|
|
2383
2634
|
exports.retry = retry;
|
|
2635
|
+
exports.romanNumerals = romanNumerals;
|
|
2384
2636
|
exports.round = round;
|
|
2385
2637
|
exports.roundBank = roundBank;
|
|
2386
2638
|
exports.roundBase = roundBase;
|
|
2387
2639
|
exports.roundCeil = roundCeil;
|
|
2388
2640
|
exports.roundFloor = roundFloor;
|
|
2641
|
+
exports.scientificNotation = scientificNotation;
|
|
2389
2642
|
exports.shuffle = shuffle;
|
|
2390
2643
|
exports.sleep = sleep;
|
|
2391
2644
|
exports.snakeCase = snakeCase;
|