;|
Problem:
Sort strings with mixed alphabetical and numerical parts, so that
the alphabetical are sorted and for equal ones the numerical parts.
This can be changed to check the numbers only.
First we need some helper's to extract the relevant parts from the
string, then we design the comparsion function, then we pass this to the
generic sort function, as vl-sort, std-sort or std-stable-sort.
(alpha-from "CA10") => "CA"
(number-from "CA10") => 10
(vl-sort '(("R3" (37.6 16.5)) ; or std-stable-sort on plain alisp
("RA37" (31.9 24.2))
("C41" (30.7 24.2))
("C1" (20.7 2.52))
("CR91" (32.4 23.3)))
'car-alnum-cmp)
=> (("CR91" (32.4 23.3))
("C1" (20.7 2.52))
("C41" (30.7 24.2))
("RA37" (31.9 24.2))
("R3" (37.6 16.5)))
|;
(defun car-alnum-cmp (a b)
(< (alnum-cmp (car a) (car b))))
;;; alpha-numerical sort comparison function
;;; for keys like "CA99", with ordered alphabetic and numerical parts
(defun alnum-cmp (a b / as bs)
;; get the alpha parts at the front
(setq as (alpha-from a)
bs (alpha-from b))
(cond ((= as bs) (< (number-from a) (number-from b))) ; compare nums
(T (< as bs)))) ; compare strings
;;; strips out the alphabetical prefix
(defun alpha-from (s)
(setq new "")
(while (isalpha-p (ascii s))
(setq new (strcat new (substr s 1 1))
s (substr s 2)))
new)
(defun isalpha-p (i) ; this gets fooled by chars in between "Z" and "a"
(<= 65 i 122)) ; but we use it only to seperate it from nums
;;; returns the numerical remainer
(defun number-from (s) ; or zero for none
(while (isalpha-p (ascii s))
(setq s (substr s 2)))
(atoi s))
;;; by Reini Urban, 29.6.99