Skip to content

Commit 5767fdd

Browse files
committed
feat: add ratio reducer
1 parent f70cbdd commit 5767fdd

4 files changed

Lines changed: 43 additions & 7 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#### Added
66

7+
- Reducer: `ratio` for the percentage of items that pass a predicate.
78
- Source: `chain` to compose any number of Generators.
89
- Source: The `generator` type and its functions have been exposed so that
910
others can write their own Generators.

README.org

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ Looking for Transducers in other Lisps? Check out the [[https://github.com/fossk
6969
- [[#string-base-string][string, base-string]]
7070
- [[#hash-table][hash-table]]
7171
- [[#count-quantities][count, quantities]]
72-
- [[#average-median][average, median]]
72+
- [[#average-median-ratio][average, median, ratio]]
7373
- [[#any-all][any?, all?]]
7474
- [[#partition][partition]]
7575
- [[#first-last-find][first, last, find]]
@@ -750,9 +750,9 @@ predicate.
750750
#+RESULTS:
751751
: #<COMMON-LISP:HASH-TABLE :TEST EQL :COUNT 5 {10094FE823}>
752752

753-
*** average, median
753+
*** average, median, ratio
754754

755-
Calculate the average value of all numeric elements in a transduction.
755+
=average=: Calculate the average value of all numeric elements in a transduction.
756756

757757
#+begin_src lisp :exports both
758758
(in-package :transducers)
@@ -762,9 +762,9 @@ Calculate the average value of all numeric elements in a transduction.
762762
#+RESULTS:
763763
: 7/2
764764

765-
Calculate the median value of all elements in a transduction, provided that they
766-
are numbers, strings, or characters. The elements are sorted once before the
767-
median is extracted.
765+
=median=: Calculate the median value of all elements in a transduction, provided
766+
that they are numbers, strings, or characters. The elements are sorted once
767+
before the median is extracted.
768768

769769
#+begin_src lisp :exports both
770770
(in-package :transducers)
@@ -774,6 +774,17 @@ median is extracted.
774774
#+RESULTS:
775775
: 1
776776

777+
=ratio=: The percentage of items that satisfied a predicate. The final value will
778+
always be between 0 and 1.
779+
780+
#+begin_src lisp :exports both
781+
(in-package :transducers)
782+
(transduce #'pass (ratio #'evenp) #(1 2 3 4 5 6))
783+
#+end_src
784+
785+
#+RESULTS:
786+
: 1/2
787+
777788
*** any?, all?
778789

779790
Yield =t= if any element in the transduction satisfies PRED. Short-circuits the

transducers/package.lisp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
(:shadow #:map #:concatenate #:log #:step #:split
44
#:string #:base-string #:vector #:bit-vector #:hash-table
55
#:cons #:count #:first #:last #:max #:min #:find
6-
#:random)
6+
#:random #:ratio)
77
;; --- Entry Points --- ;;
88
(:export #:transduce)
99
;; --- Transducers -- ;;

transducers/reducers.lisp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,30 @@ The elements are sorted once before the median is extracted.
134134
#+nil
135135
(transduce (filter #'evenp) #'average '(1 3 5))
136136

137+
(defun ratio (pred)
138+
"Reducer: The percentage of items that satisfied a predicate. The final value
139+
will always be between 0 and 1.
140+
141+
# Conditions
142+
143+
- `empty-transduction': when no values made it through the transduction."
144+
(lambda (&optional (acc nil a?) (input nil i?))
145+
(cond ((and a? i?)
146+
(incf (avg-count acc))
147+
(when (funcall pred input)
148+
(incf (avg-total acc)))
149+
acc)
150+
((and a? (not i?))
151+
(if (zerop (avg-count acc))
152+
(error 'empty-transduction :msg "`ratio' called on an empty transduction.")
153+
(/ (avg-total acc) (avg-count acc))))
154+
(t (make-avg :count 0 :total 0)))))
155+
156+
#+nil
157+
(transduce #'pass (ratio #'evenp) #(1 2 3 4 5 6))
158+
#+nil
159+
(transduce #'pass (ratio #'evenp) #())
160+
137161
(declaim (ftype (function ((function (t) *)) *) any?))
138162
(defun any? (pred)
139163
"Reducer: Yield t if any element in the transduction satisfies PRED.

0 commit comments

Comments
 (0)