1 | ;;;; sort-combinators.scm |
---|
2 | ;;;; Kon Lovett, Mar '09 |
---|
3 | |
---|
4 | (declare |
---|
5 | (usual-integrations) |
---|
6 | (generic) |
---|
7 | (inline) |
---|
8 | (local) |
---|
9 | (no-procedure-checks) |
---|
10 | (bound-to-procedure |
---|
11 | ##sys#check-closure) ) |
---|
12 | |
---|
13 | (module sort-combinators (;export |
---|
14 | group/key |
---|
15 | make-equal/key make-less-than/key) |
---|
16 | |
---|
17 | (import scheme chicken srfi-1) |
---|
18 | |
---|
19 | (require-library srfi-1) |
---|
20 | |
---|
21 | ;; Group a list of elements by some key attribute. |
---|
22 | ;; |
---|
23 | ;; The list must be in sorted order with respect to the key. |
---|
24 | ;; |
---|
25 | ;; examples: |
---|
26 | ;; (group/key identity '(1 2 3 3 4 4 4)) --> ((1) (2) (3 3) (4 4 4)) |
---|
27 | ;; (group/key car '((a 1) (a 2) (b 1))) --> '(((a 1) (a 2)) ((b 1))) |
---|
28 | |
---|
29 | (define (group/key keyproc ls #!optional (equality equal?)) |
---|
30 | (##sys#check-closure keyproc 'group/key) |
---|
31 | (##sys#check-closure equality 'group/key) |
---|
32 | (let loop ((ls ls) (acc '())) |
---|
33 | (if (null? ls) acc #;(reverse! acc) |
---|
34 | (let ((key (keyproc (car ls)))) |
---|
35 | (receive (grouped rest) (span (lambda (item) (equality key (keyproc item))) ls) |
---|
36 | (loop rest (cons grouped acc)) ) ) ) ) ) |
---|
37 | |
---|
38 | ;; Define a less-than function for a sort of a structured sequence. |
---|
39 | ;; |
---|
40 | ;; E.g. to sort a list of lists by their first items, using |
---|
41 | ;; string-case-insensitive comparison: |
---|
42 | ;; (sort ls (make-less-than/key first string-ci<?)) |
---|
43 | |
---|
44 | (define (make-less-than/key keyproc #!optional (less-than <)) |
---|
45 | (##sys#check-closure keyproc 'make-less-than/key) |
---|
46 | (##sys#check-closure less-than 'make-less-than/key) |
---|
47 | (lambda (a b) (less-than (keyproc a) (keyproc b)) ) ) |
---|
48 | |
---|
49 | ;; Define a equal function for a sort of a structured sequence. |
---|
50 | ;; |
---|
51 | ;; E.g. to sort a list of lists by their first items, using |
---|
52 | ;; string-case-insensitive comparison: |
---|
53 | ;; (make-hash-table (uni first string-ci-hash) (make-equal/key first string-ci=?)) |
---|
54 | |
---|
55 | (define (make-equal/key keyproc #!optional (equal =)) |
---|
56 | (##sys#check-closure keyproc 'make-equal/key) |
---|
57 | (##sys#check-closure equal 'make-equal/key) |
---|
58 | (lambda (a b) (equal (keyproc a) (keyproc b)) ) ) |
---|
59 | |
---|
60 | ) ;module sort-combinators |
---|