diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2022-03-02 21:10:36 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2022-03-02 21:10:36 -0800 |
commit | 782873797401693035c47040f43bdb82630c45fa (patch) | |
tree | 897c38804bfd84519f228fa4a8258f8c4b9d0f51 | |
parent | 9175dc378d5b2a6da0810d17407c3decfa91206a (diff) | |
download | txr-782873797401693035c47040f43bdb82630c45fa.tar.gz txr-782873797401693035c47040f43bdb82630c45fa.tar.bz2 txr-782873797401693035c47040f43bdb82630c45fa.zip |
New function: group-map.
* hash.c (group_map): New function.
(hash_init): group-map intrinsic registered.
* hash.h (group_map): Declared.
* tests/010/hash.tl: New test case.
* txr.1: Documented together with group-by.
Extra paren removed from group-by example.
-rw-r--r-- | hash.c | 7 | ||||
-rw-r--r-- | hash.h | 1 | ||||
-rw-r--r-- | stdlib/doc-syms.tl | 3 | ||||
-rw-r--r-- | tests/010/hash.tl | 4 | ||||
-rw-r--r-- | txr.1 | 45 |
5 files changed, 51 insertions, 9 deletions
@@ -1667,6 +1667,12 @@ val group_by(val func, val seq, struct args *hashv_args) } } +val group_map(val by_fun, val filter_fun, val seq, struct args *hashv_args) +{ + val hash = group_by(by_fun, seq, hashv_args); + return hash_update(hash, filter_fun); +} + val group_reduce(val hash, val by_fun, val reduce_fun, val seq, val initval, val filter_fun) { @@ -2135,6 +2141,7 @@ void hash_init(void) reg_fun(intern(lit("hash-subset"), user_package), func_n2(hash_subset)); reg_fun(intern(lit("hash-proper-subset"), user_package), func_n2(hash_proper_subset)); reg_fun(intern(lit("group-by"), user_package), func_n2v(group_by)); + reg_fun(intern(lit("group-map"), user_package), func_n3v(group_map)); reg_fun(intern(lit("group-reduce"), user_package), func_n6o(group_reduce, 4)); reg_fun(intern(lit("hash-update"), user_package), func_n2(hash_update)); @@ -85,6 +85,7 @@ val hash_from_alist_v(val alist, struct args *hashv_args); val hash_list(val keys, struct args *hashv_args); val hash_zip(val keys, val vals, struct args *hashv_args); val group_by(val func, val seq, struct args *hashv_args); +val group_map(val by_fun, val filter_fun, val seq, struct args *hashv_args); val group_reduce(val hash, val by_fun, val reduce_fun, val seq, val initval, val filter_fun); val hash_keys(val hash); diff --git a/stdlib/doc-syms.tl b/stdlib/doc-syms.tl index 95092836..34e139b6 100644 --- a/stdlib/doc-syms.tl +++ b/stdlib/doc-syms.tl @@ -914,7 +914,8 @@ ("grade" "N-00091853") ("greater" "N-02AC1F73") ("group" "N-03DE71BA") - ("group-by" "N-02F6F229") + ("group-by" "N-02229668") + ("group-map" "N-02229668") ("group-reduce" "N-001A208F") ("gun" "N-0323BEBD") ("handle" "N-03F7D8B5") diff --git a/tests/010/hash.tl b/tests/010/hash.tl index bb006612..7f662b51 100644 --- a/tests/010/hash.tl +++ b/tests/010/hash.tl @@ -9,8 +9,8 @@ [group-by identity '(1 1 2 2 3 3 3)] #H(() (1 (1 1)) (2 (2 2)) (3 (3 3 3))) (group-by (op mod @1 3) (range 0 10)) #H(() (0 (0 3 6 9)) (1 (1 4 7 10)) - (2 (2 5 8)))) - + (2 (2 5 8))) + [group-map (op mod @1 3) sum (range 0 10)] #H(() (0 18) (1 22) (2 15))) (mtest [group-reduce (hash) identity (do inc @1) @@ -53977,9 +53977,10 @@ with the value returned by as the datum. This value is also returned. -.coNP Function @ group-by +.coNP Functions @ group-by and @ group-map .synb -.mets (group-by < func < sequence << option *) +.mets (group-by < by-fun < sequence << option *) +.mets (group-map < by-fun < filter-fun < sequence << option *) .syne .desc The @@ -53992,7 +53993,7 @@ list or vector. Entries of the hash table are not elements of but lists of elements of .metn sequence . The function -.meta func +.meta by-fun is applied to each element of .meta sequence @@ -54007,16 +54008,48 @@ if any, consist of the same keywords that are understood by the .code hash function, and determine the properties of the hash. -.TP* Example: +The +.code group-map +fun extends the semantics of +.code group-by +with a filtering step. It groups the elements of +.meta sequence +in exactly the same manner, using +.metn by-fun . +These lists of elements are then passed to +.meta filter-fun +whose return values become the values associated with the hash table keys. + +The effect of +.code group-map +may be obtained by a combination of +.code group-by +and +.code hash-update +according to the following equivalence: + +.verb + (group-map bf ff seq) <--> (let ((h (group-by bf seq))) + (hash-update h ff)) +.brev + +.TP* Examples: Group the integers from 0 to 10 into three buckets keyed on 0, 1 and 2 according to the modulo 3 congruence: .verb - (group-by (op mod @1 3) (range 0 10))) - + (group-by (op mod @1 3) (range 0 10)) -> #H(() (0 (0 3 6 9)) (1 (1 4 7 10)) (2 (2 5 8))) .brev +Same as above, but associate the keys with the sums of the +buckets: + +.verb + [group-map (op mod @1 3) sum (range 0 10)] + -> #H(() (0 18) (1 22) (2 15)) +.brev + .coNP Function @ group-reduce .synb .mets (group-reduce < hash < classify-fun < binary-fun < seq |