Add `proportions` and `mutate-hash-values`
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