foreslash 0.3.2 → 0.3.4

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 CHANGED
@@ -1,5 +1,31 @@
1
1
  # Change Log
2
2
 
3
+ ## Version 0.3.4 - 2025-11-
4
+
5
+ Unstable version
6
+
7
+ - Feat 🥥 Functions added: `omit` `pick`
8
+ - Other fixes and improvements
9
+
10
+ 不稳定版本
11
+
12
+ - 功能 🥥 添加函数: `omit` `pick`
13
+ - 其他修复与优化
14
+
15
+ ## Version 0.3.3 - 2025-11-05
16
+
17
+ Unstable version
18
+
19
+ - Feat 🥥 Functions added: `lerp` `scientificNotation` `castArray` `romanNumerals` `randomDistribution` and so forth
20
+ - Fix 🥕 Document: Added version tags to `memo` and description to several methods
21
+ - Other fixes and improvements
22
+
23
+ 不稳定版本
24
+
25
+ - 功能 🥥 添加函数: `lerp` `scientificNotation` `castArray` `randomDistribution` 等
26
+ - 修复 🥕 文档: 补充 `memo` 的版本标签和部分方法的说明
27
+ - 其他修复与优化
28
+
3
29
  ## Version 0.3.2 - 2025-09-23
4
30
 
5
31
  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 + '&#x0305;'.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, 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}&#x00d7;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 instanceof Date) {
2116
+ if (isDate(obj)) {
1870
2117
  res = new Date(obj.valueOf());
1871
2118
  map.set(obj, res);
1872
2119
  }
1873
- else if (obj instanceof RegExp) {
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 instanceof ArrayBuffer) {
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 instanceof DataView) {
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
  }
@@ -2242,6 +2489,27 @@ function not(value) {
2242
2489
  return !Boolean(value);
2243
2490
  }
2244
2491
 
2492
+ function omit(obj, keys) {
2493
+ const res = (Object.getPrototypeOf(obj) ? {} : Object.create(null));
2494
+ const ownKeys = Reflect.ownKeys(obj);
2495
+ if (isFunction(keys)) {
2496
+ for (let i = 0; i < ownKeys.length; i++) {
2497
+ const key = ownKeys[i];
2498
+ if (!keys(obj[key], key, obj))
2499
+ res[key] = obj[key];
2500
+ }
2501
+ }
2502
+ else {
2503
+ const keysSet = new Set((isArray(keys) ? keys : [keys]).map((k) => (isNumber(k) ? String(k) : k)));
2504
+ for (let i = 0; i < ownKeys.length; i++) {
2505
+ const key = ownKeys[i];
2506
+ if (!keysSet.has(key))
2507
+ res[key] = obj[key];
2508
+ }
2509
+ }
2510
+ return res;
2511
+ }
2512
+
2245
2513
  function pass(value) {
2246
2514
  return value;
2247
2515
  }
@@ -2252,6 +2520,31 @@ function passWith(fn) {
2252
2520
  });
2253
2521
  }
2254
2522
 
2523
+ function pick(obj, keys) {
2524
+ const res = (Object.getPrototypeOf(obj) ? {} : Object.create(null));
2525
+ const ownKeys = Reflect.ownKeys(obj);
2526
+ if (isFunction(keys)) {
2527
+ for (let i = 0; i < ownKeys.length; i++) {
2528
+ const key = ownKeys[i];
2529
+ if (keys(obj[key], key, obj))
2530
+ res[key] = obj[key];
2531
+ }
2532
+ }
2533
+ else if (isArray(keys)) {
2534
+ const keysSet = new Set(ownKeys);
2535
+ for (let i = 0; i < keys.length; i++) {
2536
+ const key = keys[i];
2537
+ if (keysSet.has(isNumber(key) ? String(key) : key))
2538
+ res[key] = obj[key];
2539
+ }
2540
+ }
2541
+ else if (isString(keys) || isNumber(keys) || isSymbol(keys)) {
2542
+ if (ownKeys.includes(isNumber(keys) ? String(keys) : keys))
2543
+ res[keys] = obj[keys];
2544
+ }
2545
+ return res;
2546
+ }
2547
+
2255
2548
  function pipe(...pipeFunc) {
2256
2549
  if (pipeFunc.length === 0) {
2257
2550
  throw new Error('Invalid pipeFunc parameter: pipeFunc is empty');
@@ -2289,6 +2582,7 @@ exports.caseConvert = caseConvert;
2289
2582
  exports.caseKebab = caseKebab;
2290
2583
  exports.casePascal = casePascal;
2291
2584
  exports.caseSnake = caseSnake;
2585
+ exports.castArray = castArray;
2292
2586
  exports.chunk = chunk;
2293
2587
  exports.clamp = clamp;
2294
2588
  exports.compose = compose;
@@ -2304,6 +2598,7 @@ exports.format = format;
2304
2598
  exports.getAcceptableExtByMIME = getAcceptableExtByMIME;
2305
2599
  exports.getAcceptableMIMEByExt = getAcceptableMIMEByExt;
2306
2600
  exports.getGlobalThis = getGlobalThis;
2601
+ exports.getInitP = getInitP;
2307
2602
  exports.getTag = getTag;
2308
2603
  exports.indent = indent;
2309
2604
  exports.isArray = isArray;
@@ -2360,16 +2655,20 @@ exports.isWrapperObject = isWrapperObject;
2360
2655
  exports.isWrapperString = isWrapperString;
2361
2656
  exports.isWrapperSymbol = isWrapperSymbol;
2362
2657
  exports.kebabCase = kebabCase;
2658
+ exports.lerp = lerp;
2363
2659
  exports.memo = memo;
2364
2660
  exports.noop = noop;
2365
2661
  exports.not = not;
2662
+ exports.omit = omit;
2366
2663
  exports.parallel = parallel;
2367
2664
  exports.pascalCase = pascalCase;
2368
2665
  exports.pass = pass;
2369
2666
  exports.passWith = passWith;
2667
+ exports.pick = pick;
2370
2668
  exports.pipe = pipe;
2371
2669
  exports.randomBase32String = randomBase32String;
2372
2670
  exports.randomChoice = randomChoice;
2671
+ exports.randomDistribution = randomDistribution;
2373
2672
  exports.randomHexString = randomHexString;
2374
2673
  exports.randomInt = randomInt;
2375
2674
  exports.randomIntFloor = randomIntFloor;
@@ -2377,11 +2676,13 @@ exports.randomString = randomString;
2377
2676
  exports.range = range;
2378
2677
  exports.remove = remove;
2379
2678
  exports.retry = retry;
2679
+ exports.romanNumerals = romanNumerals;
2380
2680
  exports.round = round;
2381
2681
  exports.roundBank = roundBank;
2382
2682
  exports.roundBase = roundBase;
2383
2683
  exports.roundCeil = roundCeil;
2384
2684
  exports.roundFloor = roundFloor;
2685
+ exports.scientificNotation = scientificNotation;
2385
2686
  exports.shuffle = shuffle;
2386
2687
  exports.sleep = sleep;
2387
2688
  exports.snakeCase = snakeCase;