Re: non-lexicographic string comparison
- From: Derick Eddington <derick.eddington@xxxxxxxxx>
- Date: Sun, 15 Nov 2009 17:02:47 -0800 (PST)
On Nov 11, 5:00 am, Marco Maggi <mrc....@xxxxxxxxx> wrote:
the Tcl language has the [lsort] command with `dictionary'
sorting for strings; it means that when two strings have an
embedded number, the numbers are considered as integers by
the comparison function; so "ciao3" sorts before "ciao10".
I wonder if someone has already written such comparison
function in pure Scheme and is distributing it under a Libre
license, so that I can shamelessly include it in my
libraries. :-)
I made the function below for you. I place it in the public domain.
I don't know if it does exactly what you want.
(define (my-string<? a b)
(define str-num cons)
(define str-num-str car)
(define str-num-num cdr)
(define (->string x)
(if (string? x) x (str-num-str x)))
(define (parts x)
(define (digit? c)
(memv c (string->list "0123456789")))
(let loop ((x (reverse (string->list x)))
(str (list))
(num (list))
(accum (list)))
(define (accum-str)
(if (null? str)
accum
(cons (list->string str) accum)))
(define (accum-num)
(if (null? num)
accum
(let ((s (list->string num)))
(cons (str-num s (string->number s))
accum))))
(cond
((null? x)
(cond ((not (null? str))
(assert (null? num))
(accum-str))
((not (null? num))
(assert (null? str))
(accum-num))
(else accum)))
((digit? (car x))
(loop (cdr x)
(list)
(cons (car x) num)
(accum-str)))
(else
(loop (cdr x)
(cons (car x) str)
(list)
(accum-num))))))
(let loop ((a (parts a))
(b (parts b)))
(cond
((null? a)
(not (null? b)))
((null? b) #F)
((and (string? (car a))
(string? (car b)))
(if (string=? (car a) (car b))
(loop (cdr a) (cdr b))
(string<? (car a) (car b))))
((and (not (string? (car a)))
(not (string? (car b))))
(if (= (str-num-num (car a))
(str-num-num (car b)))
(loop (cdr a) (cdr b))
(< (str-num-num (car a))
(str-num-num (car b)))))
(else
(string<? (->string (car a))
(->string (car b)))))))
(my-string<? "123" "45")#F
(my-string<? "ciao3" "ciao10")#T
(my-string<? "foo4bar3zab10" "foo4bar3zab2")#F
(my-string<? "foo4bar3zab" "foo4bar10")#T
(my-string<? "foo12" "12foo")#F
(my-string<? "12bar" "foobar")#T
(my-string<? "12.3" "12.10")#T
(my-string<? "12.3" "12,10")#F
(list-sort my-string<? (quote ("foo123" "foo42" "foo7")))("foo7" "foo42" "foo123")
--
: Derick
----------------------------------------------------------------
.
- Follow-Ups:
- Re: non-lexicographic string comparison
- From: Marco Maggi
- Re: non-lexicographic string comparison
- References:
- non-lexicographic string comparison
- From: Marco Maggi
- non-lexicographic string comparison
- Prev by Date: [nausicaa's library of the week] Nausicaa/SQLite 2009-11-15 tag 0.1b0
- Next by Date: Reference for STk
- Previous by thread: non-lexicographic string comparison
- Next by thread: Re: non-lexicographic string comparison
- Index(es):
Relevant Pages
|