summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--eval.c2
-rw-r--r--lib.c25
-rw-r--r--lib.h3
-rw-r--r--tests/012/sort.tl5
-rw-r--r--txr.144
5 files changed, 75 insertions, 4 deletions
diff --git a/eval.c b/eval.c
index d53a20be..d5cc61c8 100644
--- a/eval.c
+++ b/eval.c
@@ -7424,6 +7424,8 @@ void eval_init(void)
reg_fun(intern(lit("unique"), user_package), func_n2ov(unique, 1));
reg_fun(intern(lit("uniq"), user_package), func_n1(uniq));
reg_fun(intern(lit("grade"), user_package), func_n3o(grade, 1));
+ reg_fun(intern(lit("hist-sort"), user_package), func_n1v(hist_sort));
+
reg_fun(intern(lit("nrot"), user_package), func_n2o(nrot, 1));
reg_fun(intern(lit("rot"), user_package), func_n2o(rot, 1));
diff --git a/lib.c b/lib.c
index a4f5db85..8d0317c7 100644
--- a/lib.c
+++ b/lib.c
@@ -133,7 +133,7 @@ val nil_string;
val identity_f, identity_star_f;
val equal_f, eql_f, eq_f, car_f, cdr_f, null_f;
-val list_f, less_f, greater_f;
+val list_f, less_f, greater_f, gt_f;
val prog_string;
@@ -175,6 +175,8 @@ const seq_kind_t seq_kind_tab[MAXTYPE+1] = {
SEQ_NOTSEQ, /* DARG */
};
+static val hist_succ_f;
+
val identity(val obj)
{
return obj;
@@ -11565,6 +11567,20 @@ val grade(val seq, val lessfun, val keyfun_in)
return nil;
}
+static val hist_succ(val left, val right)
+{
+ (void) right;
+ return succ(left);
+}
+
+val hist_sort(val seq, varg hashv_args)
+{
+ val hash = group_reduce(hashv(hashv_args),
+ identity_f, hist_succ_f,
+ seq, zero, nil);
+ return nsort(hash_alist(hash), gt_f, cdr_f);
+}
+
val nrot(val seq, val n_in)
{
val len = length(seq);
@@ -13957,8 +13973,8 @@ static void obj_init(void)
&user_package, &public_package,
&equal_f, &eq_f, &eql_f,
&car_f, &cdr_f, &null_f, &list_f,
- &identity_f, &identity_star_f, &less_f, &greater_f,
- &prog_string, &cobj_hash, &lazy_streams_binding,
+ &identity_f, &identity_star_f, &less_f, &greater_f, &gt_f,
+ &prog_string, &cobj_hash, &lazy_streams_binding, &hist_succ_f,
convert(val *, 0));
nil_string = lit("nil");
@@ -14126,9 +14142,12 @@ static void obj_init(void)
list_f = func_n0v(listv);
less_f = func_n2(less);
greater_f = func_n2(greater);
+ gt_f = func_n2(gt);
prog_string = string(progname);
cobj_hash = make_hash(hash_weak_none, nil);
+
+ hist_succ_f = func_n2(hist_succ);
}
static val simple_qref_args_p(val args, val pos)
diff --git a/lib.h b/lib.h
index e3cc0f8b..3d49e7c9 100644
--- a/lib.h
+++ b/lib.h
@@ -705,7 +705,7 @@ extern val null_string;
extern val identity_f, identity_star_f;
extern val equal_f, eql_f, eq_f, car_f, cdr_f, null_f;
-extern val list_f, less_f, greater_f;
+extern val list_f, less_f, greater_f, gt_f;
extern val prog_string;
@@ -1340,6 +1340,7 @@ val sort_group(val seq, val keyfun, val lessfun);
val unique(val seq, val keyfun, varg hashv_args);
val uniq(val seq);
val grade(val seq, val lessfun, val keyfun_in);
+val hist_sort(val seq, varg hashv_args);
val nrot(val seq, val n_in);
val rot(val seq, val n_in);
val find(val list, val key, val testfun, val keyfun);
diff --git a/tests/012/sort.tl b/tests/012/sort.tl
index 03c122d3..92811715 100644
--- a/tests/012/sort.tl
+++ b/tests/012/sort.tl
@@ -88,3 +88,8 @@
(((a 1) (a 2) (a 3) (a 4))
((b 1) (b 2))
((c 2) (c 1))))
+
+(mtest
+ (hist-sort nil) nil
+ (hist-sort '(3 4 5)) ((3 . 1) (4 . 1) (5 . 1))
+ (hist-sort '("a" "b" "c" "a" "b" "a" "b" "a")) (("a" . 4) ("b" . 3) ("c" . 1)))
diff --git a/txr.1 b/txr.1
index 15c7218c..4364caab 100644
--- a/txr.1
+++ b/txr.1
@@ -56576,6 +56576,50 @@ Separate the integers 1\(en10 into even and odd, and sum these groups:
-> #H(() (t 30) (nil 25))
.brev
+.coNP Function @ hist-sort
+.synb
+.mets (hist-sort < sequence << option *)
+.syne
+.desc
+The
+.code hist-sort
+function produces a histogram in the form of an association list,
+which is sorted in descending order of frequency. The keys in the
+association list are elements of
+.meta sequence
+and the values are the frequency values: positive integers
+indicating how many times the keys occur in
+.metn sequence .
+
+Note: for a description of association lists, see the
+.code assoc
+function, and the section Association Lists in which its description is
+contained.
+
+The
+.code hist-sort
+function works by internally constructing a hash table, which is not
+returned. Elements of
+.meta sequence
+serve as keys in that hash. The trailing arguments
+.mono
+.meti << option *
+.onom
+if any, consist of the same keywords that are understood by the
+.code hash
+function, and determine the properties of that hash.
+
+.TP* Examples
+
+.verb
+(hist-sort nil) -> nil
+
+(hist-sort '(3 4 5)) -> ((3 . 1) (4 . 1) (5 . 1))
+
+(hist-sort '("a" "b" "c" "a" "b" "a" "b" "a"))
+-> (("a" . 4) ("b" . 3) ("c" . 1))
+.brev
+
.coNP Functions @ make-similar-hash and @ copy-hash
.synb
.mets (make-similar-hash << hash )