emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Enhance seq-min and seq-max (was: stream.el)


From: Michael Heerdegen
Subject: Enhance seq-min and seq-max (was: stream.el)
Date: Sat, 15 Jun 2019 02:25:06 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/27.0.50 (gnu/linux)

Nicolas Petton <address@hidden> writes:

> It's ok to fix them, but I'd like to stay involved at least.

Ok, great.

I would like to extend seq-min and seq-max to allow (a) arbitrary
comparison functions and (b) key functions like in cl, so that you can
find e.g. the longest string in a sequence of strings.  I miss this
functionality, AFAIK cl-lib also can't do it.

Like this, maybe?

From 3cbaf1316de41687a6a3a6d67e4cc773769999c3 Mon Sep 17 00:00:00 2001
From: Michael Heerdegen <address@hidden>
Date: Fri, 10 May 2019 15:08:57 +0200
Subject: [PATCH] WIP: Enhance seq-min and seq-max

---
 lisp/emacs-lisp/seq.el | 34 +++++++++++++++++++++++++++-------
 1 file changed, 27 insertions(+), 7 deletions(-)

diff --git a/lisp/emacs-lisp/seq.el b/lisp/emacs-lisp/seq.el
index 3413cd1513..ddd8f3161c 100644
--- a/lisp/emacs-lisp/seq.el
+++ b/lisp/emacs-lisp/seq.el
@@ -451,15 +451,35 @@ seq-group-by
    (seq-reverse sequence)
    nil))

-(cl-defgeneric seq-min (sequence)
+(cl-defgeneric seq-min (sequence &optional predicate key)
   "Return the smallest element of SEQUENCE.
-SEQUENCE must be a sequence of numbers or markers."
-  (apply #'min (seq-into sequence 'list)))
-
-(cl-defgeneric seq-max (sequence)
+With PREDICATE given, use it to compare elements.  The default is
+`<'.
+With function KEY given, call it on the individual elements and
+compare the results instead of the elements."
+  (if predicate
+      (seq-reduce
+       (if key
+           (lambda (x y)
+             (if (funcall predicate (funcall key y) (funcall key x)) y x))
+         (lambda (x y) (if (funcall predicate y x) y x)))
+       sequence (car sequence))
+    (apply #'min (seq-into sequence 'list))))
+
+(cl-defgeneric seq-max (sequence &optional predicate key)
   "Return the largest element of SEQUENCE.
-SEQUENCE must be a sequence of numbers or markers."
-  (apply #'max (seq-into sequence 'list)))
+With PREDICATE given, use it to compare elements.  The default is
+`<'.
+With function KEY given, call it on the individual elements and
+compare the results instead of the elements."
+  (if predicate
+      (seq-reduce
+       (if key
+           (lambda (x y)
+             (if (funcall predicate (funcall key x) (funcall key y)) y x))
+         (lambda (x y) (if (funcall predicate x y) y x)))
+       sequence (car sequence))
+    (apply #'max (seq-into sequence 'list))))

 (defun seq--count-successive (pred sequence)
   "Return the number of successive elements for which (PRED element) is 
non-nil in SEQUENCE."
--
2.20.1

I made it so that if the result is ambiguous (e.g. multiple strings with
equal length), the first one is returned, but that is not explicitly
documented.

Regards,

Michael.

reply via email to

[Prev in Thread] Current Thread [Next in Thread]