1 | /**
|
2 | * Utility module to work with key-value stores.
|
3 | *
|
4 | * @module map
|
5 | */
|
6 |
|
7 | /**
|
8 | * Creates a new Map instance.
|
9 | *
|
10 | * @function
|
11 | * @return {Map<any, any>}
|
12 | *
|
13 | * @function
|
14 | */
|
15 | export const create = () => new Map()
|
16 |
|
17 | /**
|
18 | * Copy a Map object into a fresh Map object.
|
19 | *
|
20 | * @function
|
21 | * @template X,Y
|
22 | * @param {Map<X,Y>} m
|
23 | * @return {Map<X,Y>}
|
24 | */
|
25 | export const copy = m => {
|
26 | const r = create()
|
27 | m.forEach((v, k) => { r.set(k, v) })
|
28 | return r
|
29 | }
|
30 |
|
31 | /**
|
32 | * Get map property. Create T if property is undefined and set T on map.
|
33 | *
|
34 | * ```js
|
35 | * const listeners = map.setIfUndefined(events, 'eventName', set.create)
|
36 | * listeners.add(listener)
|
37 | * ```
|
38 | *
|
39 | * @function
|
40 | * @template T,K
|
41 | * @param {Map<K, T>} map
|
42 | * @param {K} key
|
43 | * @param {function():T} createT
|
44 | * @return {T}
|
45 | */
|
46 | export const setIfUndefined = (map, key, createT) => {
|
47 | let set = map.get(key)
|
48 | if (set === undefined) {
|
49 | map.set(key, set = createT())
|
50 | }
|
51 | return set
|
52 | }
|
53 |
|
54 | /**
|
55 | * Creates an Array and populates it with the content of all key-value pairs using the `f(value, key)` function.
|
56 | *
|
57 | * @function
|
58 | * @template K
|
59 | * @template V
|
60 | * @template R
|
61 | * @param {Map<K,V>} m
|
62 | * @param {function(V,K):R} f
|
63 | * @return {Array<R>}
|
64 | */
|
65 | export const map = (m, f) => {
|
66 | const res = []
|
67 | for (const [key, value] of m) {
|
68 | res.push(f(value, key))
|
69 | }
|
70 | return res
|
71 | }
|
72 |
|
73 | /**
|
74 | * Tests whether any key-value pairs pass the test implemented by `f(value, key)`.
|
75 | *
|
76 | * @todo should rename to some - similarly to Array.some
|
77 | *
|
78 | * @function
|
79 | * @template K
|
80 | * @template V
|
81 | * @param {Map<K,V>} m
|
82 | * @param {function(V,K):boolean} f
|
83 | * @return {boolean}
|
84 | */
|
85 | export const any = (m, f) => {
|
86 | for (const [key, value] of m) {
|
87 | if (f(value, key)) {
|
88 | return true
|
89 | }
|
90 | }
|
91 | return false
|
92 | }
|
93 |
|
94 | /**
|
95 | * Tests whether all key-value pairs pass the test implemented by `f(value, key)`.
|
96 | *
|
97 | * @function
|
98 | * @template K
|
99 | * @template V
|
100 | * @param {Map<K,V>} m
|
101 | * @param {function(V,K):boolean} f
|
102 | * @return {boolean}
|
103 | */
|
104 | export const all = (m, f) => {
|
105 | for (const [key, value] of m) {
|
106 | if (!f(value, key)) {
|
107 | return false
|
108 | }
|
109 | }
|
110 | return true
|
111 | }
|