[cl-utilities-devel] Idea: EXTREMA function

Peter Scott sketerpot at gmail.com
Fri May 13 20:50:35 UTC 2005


The EXTREMUM function returns the smallest element of a sequence, as
determined by a binary comparison function such as #'<. A similar
thing that could be useful is a way of returning the n smallest
elements of a list (or possibly a proper sequence), determined in the
same way.

This can be done very nicely with an insertion sort, but that is
either destructive or conses a lot. Having destructive and
nondestructive versions has been proposed, and I think it's a good
idea. So, here are a couple of implementations:

(defun nextrema (list predicate n &key (key #'identity))
  (declare (optimize (speed 3) (safety 0))
	   (list list)
	   (unsigned-byte n))
  (loop for itail on list
	for i from 0
	while (< i n)
	do (loop for jtail on itail
		 do (if (funcall predicate
				 (funcall key (car jtail))
				 (funcall key (car itail)))
			(rotatef (car jtail)
				 (car itail)))))
  (subseq list 0 n))

(defun extrema (list predicate n &key (key #'identity))
  (declare (optimize (speed 3) (safety 0))
	   (list list)
	   (unsigned-byte n))
  (collecting
   (let* ((unsorted-part list))
     (loop repeat (min n (length list))
	   do (let ((smallest (extremum unsorted-part predicate :key key)))
		(collect smallest)
		(setf unsorted-part (remove smallest unsorted-part)))))))

Notice that these don't take START and END keyword arguments; this is
because I was too lazy to add them to proof-of-concept code. What
these do is perform a partial insertion sort on LIST and return the
sorted part. As you'd expect, the destructive version is faster than
the nondestructive version.

However, these implementations are probably far from optimal. Here's
another version which you may find interesting:

(defun naive-extrema (list predicate n &key (key #'identity))
  (subseq (sort list predicate :key key) 0 n))

This is the best version yet, since it works on all proper sequences
and is faster than either of the two versions that I made. Amazing how
much effort is put into the SORT function, isn't it?

-Peter



More information about the cl-utilities-devel mailing list