2c76ffecc45e

Add `proportions` and `mutate-hash-values`
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Sat, 12 Nov 2016 12:47:06 +0000
parents 3d34f6a99a24
children 71fe6a16fcef
branches/tags (none)
files DOCUMENTATION.markdown losh.lisp make-docs.lisp package.lisp

Changes

--- a/DOCUMENTATION.markdown	Thu Nov 10 14:42:47 2016 +0000
+++ b/DOCUMENTATION.markdown	Sat Nov 12 12:47:06 2016 +0000
@@ -417,6 +417,20 @@
 
   
 
+## Package `LOSH.HASH-TABLES`
+
+Utilities for operating on hash tables.
+
+### `MUTATE-HASH-VALUES` (function)
+
+    (MUTATE-HASH-VALUES FUNCTION HASH-TABLE)
+
+Replace each value in `hash-table` with the result of calling `function` on it.
+
+  Returns the hash table.
+
+  
+
 ## Package `LOSH.ITERATE`
 
 Custom `iterate` drivers and clauses.
@@ -887,6 +901,29 @@
 
   
 
+### `PROPORTIONS` (function)
+
+    (PROPORTIONS SEQUENCE &KEY (TEST 'EQL) (FLOAT T))
+
+Return a hash table containing the proportions of the items in `sequence`.
+
+  Uses `test` for the `:test` of the hash table.
+
+  If `float` is `t` the hash table values will be coerced to floats, otherwise
+  they will be left as rationals.
+
+  Example:
+
+    (proportions '(foo foo bar))
+    => {foo 0.66666
+        bar 0.33333}
+
+    (proportions '(foo foo bar) :float nil)
+    => {foo 2/3
+        bar 1/3}
+
+  
+
 ## Package `LOSH.WEIGHTLISTS`
 
 A simple data structure for choosing random items with weighted probabilities.
--- a/losh.lisp	Thu Nov 10 14:42:47 2016 +0000
+++ b/losh.lisp	Sat Nov 12 12:47:06 2016 +0000
@@ -1181,6 +1181,19 @@
                            (keywordize-clause clause))))))
 
 
+;;;; Hash Tables
+(defun mutate-hash-values (function hash-table)
+  "Replace each value in `hash-table` with the result of calling `function` on it.
+
+  Returns the hash table.
+
+  "
+  (iterate (for (key value) :in-hashtable hash-table)
+           (setf (gethash key hash-table)
+                 (funcall function value)))
+  hash-table)
+
+
 ;;;; Sequences
 (defun prefix-sums (sequence)
   "Return a list of the prefix sums of the numbers in `sequence`.
@@ -1214,6 +1227,31 @@
     (incf (gethash i result 0))
     (finally (return result))))
 
+(defun proportions (sequence &key (test 'eql) (float t))
+  "Return a hash table containing the proportions of the items in `sequence`.
+
+  Uses `test` for the `:test` of the hash table.
+
+  If `float` is `t` the hash table values will be coerced to floats, otherwise
+  they will be left as rationals.
+
+  Example:
+
+    (proportions '(foo foo bar))
+    => {foo 0.66666
+        bar 0.33333}
+
+    (proportions '(foo foo bar) :float nil)
+    => {foo 2/3
+        bar 1/3}
+
+  "
+  (let* ((freqs (frequencies sequence :test test))
+         (total (reduce #'+ (hash-table-values freqs)
+                        :initial-value (if float 1.0 1))))
+    (mutate-hash-values (lambda (v) (/ v total))
+                        freqs)))
+
 (defun group-by (function sequence &key (test #'eql) (key #'identity))
   "Return a hash table of the elements of `sequence` grouped by `function`.
 
--- a/make-docs.lisp	Thu Nov 10 14:42:47 2016 +0000
+++ b/make-docs.lisp	Sat Nov 12 12:47:06 2016 +0000
@@ -8,6 +8,7 @@
         "LOSH.DEBUGGING"
         "LOSH.ELDRITCH-HORRORS"
         "LOSH.FUNCTIONS"
+        "LOSH.HASH-TABLES"
         "LOSH.ITERATE"
         "LOSH.LICENSING"
         "LOSH.LISTS"
--- a/package.lisp	Thu Nov 10 14:42:47 2016 +0000
+++ b/package.lisp	Sat Nov 12 12:47:06 2016 +0000
@@ -141,11 +141,17 @@
     #:skip-origin
     #:macroexpand-iterate))
 
+(defpackage #:losh.hash-tables
+  (:documentation "Utilities for operating on hash tables.")
+  (:export
+    #:mutate-hash-values))
+
 (defpackage #:losh.sequences
   (:documentation "Utilities for operating on sequences.")
   (:export
     #:prefix-sums
     #:frequencies
+    #:proportions
     #:group-by))
 
 (defpackage #:losh.debugging
@@ -184,19 +190,23 @@
 
 (defpackage-inheriting #:losh
   (#:losh.arrays
+
    #:losh.control-flow
    #:losh.debugging
-   #:losh.sequences
    #:losh.eldritch-horrors
    #:losh.functions
+   #:losh.hash-tables
    #:losh.iterate
+   #:losh.licensing
    #:losh.lists
    #:losh.math
    #:losh.mutation
    #:losh.queues
    #:losh.random
+   #:losh.sequences
    #:losh.weightlists
-   #:losh.licensing)
+
+   )
   (:use
     #:cl
     #:iterate