git.fiddlerwoaroof.com
Browse code

feat: add hash-join

Edward Langley authored on 22/10/2023 18:15:22
Showing 2 changed files
... ...
@@ -423,6 +423,26 @@
423 423
                       (reverse (cdr it))))
424 424
               (alexandria:hash-table-alist groups)))))
425 425
 
426
+(defun hash-join (probe join-fn &key (test 'eql) (key 'car))
427
+  (let* ((lookup (make-hash-table :test test :size (length probe)))
428
+         (lookup-fn (functionalize lookup)))
429
+    (map nil
430
+         (lambda (it)
431
+           (setf (gethash (funcall key it)
432
+                          lookup)
433
+                 it))
434
+         probe)
435
+    (lambda (collection)
436
+      (map (etypecase collection
437
+             (list 'list)
438
+             (vector 'vector)
439
+             (sequence 'list))
440
+           (lambda (it)
441
+             (let* ((key-value (funcall key it))
442
+                    (matching-probe (funcall lookup-fn key-value)))
443
+               (funcall join-fn it matching-probe)))
444
+           collection))))
445
+
426 446
 #+nil
427 447
 (defmacro <> (arity &rest funs)
428 448
   (let ((arg-syms (loop repeat arity collect (gensym))))
... ...
@@ -22,6 +22,7 @@
22 22
            #:∘ #:suffixp #:functionalize #:inc #:group-by #:keys
23 23
            #:conj #:disj #:delay #:of-type #:transform #:calling*
24 24
            #:calling
25
+           #:hash-join
25 26
            #:tap))
26 27
 
27 28
 (defpackage :data-lens.transducers.internals