extra-utils 5.13.0 → 5.15.0

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/README.md CHANGED
@@ -87,6 +87,18 @@ function remap(
87
87
  , [newMin, newMax]: readonly [newMin: number, newMax: number]
88
88
  ): number
89
89
 
90
+ function remapToIndex(
91
+ value: number
92
+ , range: readonly [min: number, max: number]
93
+ , items: NonEmptyArray<unknown>
94
+ ): number
95
+
96
+ function remapToWeightedIndex(
97
+ value: number
98
+ , range: [min: number, max: number]
99
+ , weights: NonEmptyArray<number>
100
+ ): number
101
+
90
102
  function lerp(
91
103
  alpha: number
92
104
  , [from, to]: readonly [from: number, to: number]
@@ -115,6 +127,10 @@ function isntEmptyObject(val: object): boolean
115
127
  function isReferenceEqual(a: unknown, b: unknown): boolean
116
128
  function isShallowEqual(a: unknown, b: unknown): boolean
117
129
  function isDeepEqual(a: unknown, b: unknown): boolean
130
+
131
+ function fromEntries<Key extends number | string, Value>(
132
+ entries: Iterable<[Key, Value]>
133
+ ): Record<Key, Value>
118
134
  ```
119
135
 
120
136
  ### String
@@ -5,4 +5,6 @@ export * from './is-nan.js';
5
5
  export * from './is-number.js';
6
6
  export * from './clamp.js';
7
7
  export * from './remap.js';
8
+ export * from './remap-to-index.js';
9
+ export * from './remap-to-weighted-index.js';
8
10
  export * from './lerp.js';
@@ -5,5 +5,7 @@ export * from './is-nan.js';
5
5
  export * from './is-number.js';
6
6
  export * from './clamp.js';
7
7
  export * from './remap.js';
8
+ export * from './remap-to-index.js';
9
+ export * from './remap-to-weighted-index.js';
8
10
  export * from './lerp.js';
9
11
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/number/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAA;AAC9B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,kBAAkB,CAAA;AAChC,cAAc,aAAa,CAAA;AAC3B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA;AAC1B,cAAc,WAAW,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/number/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAA;AAC9B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,kBAAkB,CAAA;AAChC,cAAc,aAAa,CAAA;AAC3B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA;AAC1B,cAAc,qBAAqB,CAAA;AACnC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,WAAW,CAAA"}
@@ -0,0 +1,2 @@
1
+ import { NonEmptyArray } from 'justypes';
2
+ export declare function remapToIndex(value: number, range: readonly [min: number, max: number], items: NonEmptyArray<unknown>): number;
@@ -0,0 +1,8 @@
1
+ import { remap } from './remap.js';
2
+ export function remapToIndex(value, range, items) {
3
+ const index = Math.floor(remap(value, range, [0, items.length]));
4
+ return index === items.length
5
+ ? items.length - 1
6
+ : index;
7
+ }
8
+ //# sourceMappingURL=remap-to-index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remap-to-index.js","sourceRoot":"","sources":["../../src/number/remap-to-index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAElC,MAAM,UAAU,YAAY,CAC1B,KAAa,EACb,KAA0C,EAC1C,KAA6B;IAE7B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CACtB,KAAK,CACH,KAAK,EACL,KAAK,EACL,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAClB,CACF,CAAA;IAED,OAAO,KAAK,KAAK,KAAK,CAAC,MAAM;QACxB,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;QAClB,CAAC,CAAC,KAAK,CAAA;AACd,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { NonEmptyArray } from 'justypes';
2
+ export declare function remapToWeightedIndex(value: number, range: readonly [min: number, max: number], weights: NonEmptyArray<number>): number;
@@ -0,0 +1,25 @@
1
+ import { remap } from './remap.js';
2
+ import { remapToIndex } from './remap-to-index.js';
3
+ export function remapToWeightedIndex(value, range, weights) {
4
+ const newRangeMax = weights.reduce((acc, cur) => acc + Math.max(cur, 0));
5
+ if (newRangeMax === 0) {
6
+ return remapToIndex(value, range, weights);
7
+ }
8
+ else {
9
+ const newValue = remap(value, range, [0, newRangeMax]);
10
+ let remains = newRangeMax;
11
+ for (let i = weights.length; i--;) {
12
+ const weight = weights[i];
13
+ if (weight <= 0) {
14
+ continue;
15
+ }
16
+ else {
17
+ remains -= weight;
18
+ if (newValue >= remains)
19
+ return i;
20
+ }
21
+ }
22
+ throw new Error('Impossible route');
23
+ }
24
+ }
25
+ //# sourceMappingURL=remap-to-weighted-index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remap-to-weighted-index.js","sourceRoot":"","sources":["../../src/number/remap-to-weighted-index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAElD,MAAM,UAAU,oBAAoB,CAClC,KAAa,EACb,KAA0C,EAC1C,OAA8B;IAE9B,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAA;IAExE,IAAI,WAAW,KAAK,CAAC,EAAE;QAErB,OAAO,YAAY,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,CAAA;KAC3C;SAAM;QACL,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAA;QAEtD,IAAI,OAAO,GAAG,WAAW,CAAA;QACzB,KAAK,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,GAAG;YACjC,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;YACzB,IAAI,MAAM,IAAI,CAAC,EAAE;gBACf,SAAQ;aACT;iBAAM;gBACL,OAAO,IAAI,MAAM,CAAA;gBACjB,IAAI,QAAQ,IAAI,OAAO;oBAAE,OAAO,CAAC,CAAA;aAClC;SACF;QAED,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAA;KACpC;AACH,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function fromEntries<Key extends number | string, Value>(entries: Iterable<[Key, Value]>): Record<Key, Value>;
@@ -0,0 +1,4 @@
1
+ export function fromEntries(entries) {
2
+ return Object.fromEntries(entries);
3
+ }
4
+ //# sourceMappingURL=from-entries.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"from-entries.js","sourceRoot":"","sources":["../../src/object/from-entries.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,WAAW,CACzB,OAA+B;IAE/B,OAAO,MAAM,CAAC,WAAW,CAAC,OAAO,CAAuB,CAAA;AAC1D,CAAC"}
@@ -4,3 +4,4 @@ export * from './is-plain-object.js';
4
4
  export * from './is-reference-equal.js';
5
5
  export * from './is-shallow-equal.js';
6
6
  export * from './is-deep-equal.js';
7
+ export * from './from-entries.js';
@@ -4,4 +4,5 @@ export * from './is-plain-object.js';
4
4
  export * from './is-reference-equal.js';
5
5
  export * from './is-shallow-equal.js';
6
6
  export * from './is-deep-equal.js';
7
+ export * from './from-entries.js';
7
8
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/object/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAA;AACpC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,sBAAsB,CAAA;AACpC,cAAc,yBAAyB,CAAA;AACvC,cAAc,uBAAuB,CAAA;AACrC,cAAc,oBAAoB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/object/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAA;AACpC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,sBAAsB,CAAA;AACpC,cAAc,yBAAyB,CAAA;AACvC,cAAc,uBAAuB,CAAA;AACrC,cAAc,oBAAoB,CAAA;AAClC,cAAc,mBAAmB,CAAA"}
@@ -3,7 +3,7 @@ export function isURLString(text) {
3
3
  new URL(text);
4
4
  return true;
5
5
  }
6
- catch (_a) {
6
+ catch {
7
7
  return false;
8
8
  }
9
9
  }
@@ -1 +1 @@
1
- {"version":3,"file":"is-url-string.js","sourceRoot":"","sources":["../../src/string/is-url-string.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,IAAI;QACF,IAAI,GAAG,CAAC,IAAI,CAAC,CAAA;QACb,OAAO,IAAI,CAAA;KACZ;IAAC,WAAM;QACN,OAAO,KAAK,CAAA;KACb;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;AAC3B,CAAC"}
1
+ {"version":3,"file":"is-url-string.js","sourceRoot":"","sources":["../../src/string/is-url-string.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,IAAI;QACF,IAAI,GAAG,CAAC,IAAI,CAAC,CAAA;QACb,OAAO,IAAI,CAAA;KACZ;IAAC,MAAM;QACN,OAAO,KAAK,CAAA;KACb;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;AAC3B,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "extra-utils",
3
- "version": "5.13.0",
3
+ "version": "5.15.0",
4
4
  "description": "Utilities for JavaScript and Typescript",
5
5
  "files": [
6
6
  "src",
@@ -5,4 +5,6 @@ export * from './is-nan.js'
5
5
  export * from './is-number.js'
6
6
  export * from './clamp.js'
7
7
  export * from './remap.js'
8
+ export * from './remap-to-index.js'
9
+ export * from './remap-to-weighted-index.js'
8
10
  export * from './lerp.js'
@@ -0,0 +1,20 @@
1
+ import { NonEmptyArray } from 'justypes'
2
+ import { remap } from './remap.js'
3
+
4
+ export function remapToIndex(
5
+ value: number
6
+ , range: readonly [min: number, max: number]
7
+ , items: NonEmptyArray<unknown>
8
+ ): number {
9
+ const index = Math.floor(
10
+ remap(
11
+ value
12
+ , range
13
+ , [0, items.length]
14
+ )
15
+ )
16
+
17
+ return index === items.length
18
+ ? items.length - 1
19
+ : index
20
+ }
@@ -0,0 +1,31 @@
1
+ import { NonEmptyArray } from 'justypes'
2
+ import { remap } from './remap.js'
3
+ import { remapToIndex } from './remap-to-index.js'
4
+
5
+ export function remapToWeightedIndex(
6
+ value: number
7
+ , range: readonly [min: number, max: number]
8
+ , weights: NonEmptyArray<number>
9
+ ): number {
10
+ const newRangeMax = weights.reduce((acc, cur) => acc + Math.max(cur, 0))
11
+
12
+ if (newRangeMax === 0) {
13
+ // 只有在所有权重都小于等于0的情况下会进入此路径, 所有权重此时都被视为1.
14
+ return remapToIndex(value, range, weights)
15
+ } else {
16
+ const newValue = remap(value, range, [0, newRangeMax])
17
+
18
+ let remains = newRangeMax
19
+ for (let i = weights.length; i--;) {
20
+ const weight = weights[i]
21
+ if (weight <= 0) {
22
+ continue
23
+ } else {
24
+ remains -= weight
25
+ if (newValue >= remains) return i
26
+ }
27
+ }
28
+
29
+ throw new Error('Impossible route')
30
+ }
31
+ }
@@ -0,0 +1,5 @@
1
+ export function fromEntries<Key extends number | string, Value>(
2
+ entries: Iterable<[Key, Value]>
3
+ ): Record<Key, Value> {
4
+ return Object.fromEntries(entries) as Record<Key, Value>
5
+ }
@@ -4,3 +4,4 @@ export * from './is-plain-object.js'
4
4
  export * from './is-reference-equal.js'
5
5
  export * from './is-shallow-equal.js'
6
6
  export * from './is-deep-equal.js'
7
+ export * from './from-entries.js'