summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--eval.c2
-rw-r--r--lib.c37
-rw-r--r--lib.h2
-rw-r--r--tests/012/seq.tl22
-rw-r--r--txr.125
5 files changed, 86 insertions, 2 deletions
diff --git a/eval.c b/eval.c
index a55fdc60..e8d57ff0 100644
--- a/eval.c
+++ b/eval.c
@@ -7794,8 +7794,10 @@ void eval_init(void)
reg_fun(intern(lit("find-if"), user_package), func_n3o(find_if, 2));
reg_fun(intern(lit("rfind-if"), user_package), func_n3o(rfind_if, 2));
reg_fun(intern(lit("find-max"), user_package), func_n3o(find_max, 1));
+ reg_fun(intern(lit("find-maxes"), user_package), func_n3o(find_maxes, 1));
reg_fun(intern(lit("find-max-key"), user_package), func_n3o(find_max_key, 1));
reg_fun(intern(lit("find-min"), user_package), func_n3o(find_min, 1));
+ reg_fun(intern(lit("find-mins"), user_package), func_n3o(find_mins, 1));
reg_fun(intern(lit("find-min-key"), user_package), func_n3o(find_min_key, 1));
reg_fun(intern(lit("find-true"), user_package), func_n3o(find_true, 2));
reg_fun(intern(lit("multi-sort"), user_package), func_n3o(multi_sort, 2));
diff --git a/lib.c b/lib.c
index 009e2596..15902fbc 100644
--- a/lib.c
+++ b/lib.c
@@ -12055,6 +12055,38 @@ val find_max(val seq, val testfun_in, val keyfun_in)
return nil;
}
+val find_maxes(val seq, val testfun_in, val keyfun_in)
+{
+ val self = lit("find-maxes");
+ val testfun = default_arg(testfun_in, greater_f);
+ val keyfun = default_arg(keyfun_in, identity_f);
+ seq_iter_t iter;
+ val elem;
+ seq_build_t build;
+
+ seq_iter_init(self, &iter, seq);
+ seq_build_init(self, &build, seq);
+
+ if (seq_get(&iter, &elem)) {
+ val maxkey = funcall1(keyfun, elem);
+
+ seq_add(&build, elem);
+
+ while (seq_get(&iter, &elem)) {
+ val key = funcall1(keyfun, elem);
+ if (funcall2(testfun, key, maxkey)) {
+ maxkey = key;
+ seq_build_init(self, &build, seq);
+ seq_add(&build, elem);
+ } else if (!funcall2(testfun, maxkey, key)) {
+ seq_add(&build, elem);
+ }
+ }
+ }
+
+ return seq_finish(&build);
+}
+
val find_max_key(val seq, val testfun_in, val keyfun_in)
{
val self = lit("find-max-key");
@@ -12085,6 +12117,11 @@ val find_min(val seq, val testfun, val keyfun)
return find_max(seq, default_arg(testfun, less_f), keyfun);
}
+val find_mins(val seq, val testfun, val keyfun)
+{
+ return find_maxes(seq, default_arg(testfun, less_f), keyfun);
+}
+
val find_min_key(val seq, val testfun, val keyfun)
{
return find_max_key(seq, default_arg(testfun, less_f), keyfun);
diff --git a/lib.h b/lib.h
index 5cb52990..5bc180df 100644
--- a/lib.h
+++ b/lib.h
@@ -1400,8 +1400,10 @@ val rfind(val list, val key, val testfun, val keyfun);
val find_if(val pred, val list, val key);
val rfind_if(val pred, val list, val key);
val find_max(val seq, val testfun, val keyfun);
+val find_maxes(val seq, val testfun_in, val keyfun_in);
val find_max_key(val seq, val testfun, val keyfun);
val find_min(val seq, val testfun, val keyfun);
+val find_mins(val seq, val testfun, val keyfun);
val find_min_key(val seq, val testfun, val keyfun);
val find_true(val pred, val list, val keyfun);
val posqual(val obj, val list);
diff --git a/tests/012/seq.tl b/tests/012/seq.tl
index 45cf2b67..171ad300 100644
--- a/tests/012/seq.tl
+++ b/tests/012/seq.tl
@@ -464,6 +464,28 @@
[find-max-key '("alpha" "charlie" "aardvark" "bravo") less upcase-str] "AARDVARK"
[find-max-key #H(() (a 1) (b 2) (c 3)) : cdr] 3)
+(mtest
+ (find-maxes nil) nil
+ (find-maxes '(1 1 1 1 1)) (1 1 1 1 1)
+ (find-maxes '(2 1 1 1 1)) (2)
+ (find-maxes '(2 1 1 1 2)) (2 2)
+ (find-maxes '(2 1 2 1 2)) (2 2 2))
+
+(mtest
+ (find-maxes #()) #()
+ (find-maxes '(1 1 1 1 1)) (1 1 1 1 1)
+ (find-maxes '(2 1 1 1 1)) (2)
+ (find-maxes '(2 1 1 1 2)) (2 2)
+ (find-maxes '(2 1 2 1 2)) (2 2 2))
+
+(mtest
+ (find-maxes "") ""
+ (find-maxes "abracadabra") "rr"
+ (find-mins "abracadabra") "aaaaa")
+
+(test
+ (find-mins -10..11 : [callf * pppred ppred]) (2 3))
+
(defvarl fn (do and
(chr-isdigit @1)
(not (chr-isdigit @2))))
diff --git a/txr.1 b/txr.1
index 942d79c3..c47d5fc6 100644
--- a/txr.1
+++ b/txr.1
@@ -37729,6 +37729,27 @@ is the one that is reported. See the notes under
.code pos-max
regarding duplicate maxima.
+.coNP Functions @ find-maxes and @ find-mins
+.synb
+.mets (find-maxes < iterable >> [ testfun <> [ keyfun ]])
+.mets (find-mins < iterable >> [ testfun <> [ keyfun ]])
+.syne
+.desc
+The
+.code find-maxes
+and
+.code find-mins
+functions have the same argument conventions as, respectively,
+.code find-max
+and
+.codn find-min .
+These functions differ in that they return a sequence of all the elements of
+.meta iterable
+which maximize the value of
+.metn keyfun .
+The returned sequence is of the same kind as
+.metn iterable .
+
.coNP Functions @ find-max-key and @ find-min-key
.synb
.mets (find-max-key < iterable [ testfun <> [ keyfun ]])
@@ -37736,9 +37757,9 @@ regarding duplicate maxima.
.syne
.desc
The
-.code find-min-key
-and
.code find-max-key
+and
+.code find-min-key
functions have the same argument conventions as, respectively,
.code find-max
and