-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathzphash.zp
102 lines (87 loc) · 4.21 KB
/
zphash.zp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
(define (hash:values-map f h) "map operation on all hashmap values" (map f (hash:values h)))
(define (hash:values-reduce f acc h) "reduce operation on all hashmap values" (reduce f acc (hash:values h)))
(define (hash:values-filter f h) "filter operation on all hashmap values" (filter f (hash:values h)))
(define (hash:keys-map f h) "map operation on all hashmap keys" (map f (hash:keys h)))
(define (hash:keys-reduce f acc h) "reduce operation on all hashmap keys" (reduce f acc (hash:keys h)))
(define (hash:keys-filter f h) "filter operation on all hashmap keys" (filter f (hash:keys h)))
(define (hash:kv-map f h) "map operation on all hashmap pairs"
(map f (hash:keys-map (lambda (x) (list x (h x))) h)))
(define (hash:kv-reduce f acc h) "reduce operation on all hashmap pairs"
(reduce f acc (hash:keys-map (lambda (x) (list x (h x))) h)))
(define (hash:kv-filter f h) "filter operation on all hashmap pairs"
(filter f (hash:keys-map (lambda (x) (list x (h x))) h)))
(define (hash:filter-by-keys f h) "filter operation on hashmap keys; returns hashmap"
(let* ((keys (filter f (hash:keys h)))
(vals (map (lambda (e) (h e)) keys)))
(make-hash (zip keys vals))))
(define (hash:filter-by-vals f h) "filter operation on hashmap vals; returns hashmap"
(let* ((keys (filter (lambda (k) (f (h k))) (hash:keys h)))
(vals (map (lambda (e) (h e)) keys)))
(make-hash (zip keys vals))))
(define (hash:eqv? hash test) "tests two hashmaps for equality"
(and (reduce (lambda (acc x) (and acc (eq? (hash x) (test x)))) #t (hash:keys hash))
(reduce (lambda (acc x) (and acc (eq? (hash x) (test x)))) #t (hash:keys test))))
(define (hash:remove-empty hash) "removes empty values from a hashmap"
(hash:filter-by-vals (lambda (x) (truthy? x)) hash))
(define (hash:reverse-hash hash) "reverses the hash-map, i.e. reversing the relationship of all key-value pairs"
(make-hash (hash:keys-map (lambda (key) (list (hash key) key)) hash)))
(define (hash:set hash key value) "sets the hashmaps key value pair"
(make-hash hash (make-hash key value)))
(define-syntax hash:set!
(syntax-rules ()
((_ hash key value)
(set! hash (hash:set hash key value)))))
(define (hash:update hash key f) "updates the current hash value under the key through applying f"
(hash:set hash key (f (hash key))))
(define-syntax hash:update!
(syntax-rules ()
((_ hash key f)
(set! hash (hash:update hash key f)))))
(define (hash:merge . hashes) "merges multiple hash maps"
(apply make-hash hashes))
(define (hash:merge-with fun . hashes)
"merges multiple hashes with a collision function.
params:
- fun: the function that merges the collisions
- hashes: the hashes (vararg)
complexity: O(n*3+n*k) where k is the complexity of the collision function
returns: the merged hashmap"
(let ((all-keys (list:flatten (map hash:keys hashes)))
(reducer (lambda (k)
(|> hashes
(curry filter ($ (in? % k)))
(curry map ($ (% k)))
($ (list k (apply fun %)))))))
(make-hash (map reducer all-keys))))
(define-syntax hash:merge!
(syntax-rules ()
((_ h1 h2)
(set! h1 (hash:merge h1 h2)))))
(define (hash:deep-merge h1 h2) "merges two hash maps deeply"
(cond
((list? h1) (++ h1 h2))
((hash-map? h1)
(let ((not-there (apply make-hash (hash:kv-filter (lambda (kv) (not (in? h1 (car kv)))) h2)))
(filt (lambda (kv)
(let ((fst (car kv)))
(if (in? h2 fst)
(list fst (hash:deep-merge (cadr kv) (h2 fst)))
kv)))))
(apply make-hash (++ (hash:kv-map filt h1) not-there))))
(else h2)))
(define (hash:rename-keys hash new-keys)
"Returns the hashmap <par>hash</par> with the keys in <par>new-keys</par>
renamed to the vals therein.
params:
- hash: the hashmap to mutate
- new-keys: the rename rules
complexity: O(n*2) where n is the size of new-keys
returns: the mutated hashmap"
(hash:kv-reduce
(lambda (acc kv)
(let ((old (car kv)))
(if (in? hash old)
(hash:set acc (cadr kv) (get-from hash old))
acc)))
(reduce hash:remove hash (hash:keys new-keys))
new-keys))