Browse code
Add partition to string-utils
Showing 2 changed files
... | ... |
@@ -10,3 +10,40 @@ |
10 | 10 |
(insert-at (position-if predicate string) |
11 | 11 |
item |
12 | 12 |
string)) |
13 |
+ |
|
14 |
+(defmacro expand-branch (condition form) |
|
15 |
+ ;;; intentionally expands form twice: this should be ok, because |
|
16 |
+ ;;; only one side of the if will execute |
|
17 |
+ `(if ,condition |
|
18 |
+ ,form |
|
19 |
+ ,form)) |
|
20 |
+ |
|
21 |
+(defun partition (at string &key from-end) |
|
22 |
+ (let ((from-end (not (not from-end)))) |
|
23 |
+ (flet ((partition-char (char string from-end) |
|
24 |
+ (declare (type character char) |
|
25 |
+ (type string string) |
|
26 |
+ (type boolean from-end) |
|
27 |
+ (optimize (speed 3))) |
|
28 |
+ (let ((pos (expand-branch from-end (position char string :from-end from-end)))) |
|
29 |
+ (if pos |
|
30 |
+ (list (subseq string 0 pos) |
|
31 |
+ (subseq string (1+ pos))) |
|
32 |
+ (list string |
|
33 |
+ nil)))) |
|
34 |
+ (partition-subseq (subseq string from-end) |
|
35 |
+ (declare (type sequence subseq) |
|
36 |
+ (type string string) |
|
37 |
+ (type boolean from-end) |
|
38 |
+ (optimize (speed 3))) |
|
39 |
+ (let ((pos (expand-branch from-end (search subseq string :from-end from-end)))) |
|
40 |
+ (if pos |
|
41 |
+ (list (subseq string 0 pos) |
|
42 |
+ (subseq string (+ (length subseq) pos))) |
|
43 |
+ (list string |
|
44 |
+ nil))))) |
|
45 |
+ (declare (inline partition-char partition-subseq) |
|
46 |
+ (optimize (speed 3))) |
|
47 |
+ (typecase at |
|
48 |
+ (character (partition-char at string from-end)) |
|
49 |
+ (sequence (partition-subseq at string from-end)))))) |
... | ... |
@@ -5,6 +5,48 @@ |
5 | 5 |
(length b)) |
6 | 6 |
(every 'equal a b))) |
7 | 7 |
|
8 |
+(progn |
|
9 |
+ (st:deftest string-partition-as-expected-1 () |
|
10 |
+ (st:should be vos-equal |
|
11 |
+ '("b" "d") |
|
12 |
+ (partition "aa" "baad"))) |
|
13 |
+ |
|
14 |
+ (st:deftest string-partition-as-expected-1-end () |
|
15 |
+ (st:should be vos-equal |
|
16 |
+ '("ba" "") |
|
17 |
+ (partition "ad" "baad"))) |
|
18 |
+ (st:deftest string-partition-as-expected-1-begin () |
|
19 |
+ (st:should be vos-equal |
|
20 |
+ '("" "ad") |
|
21 |
+ (partition "ba" "baad"))) |
|
22 |
+ |
|
23 |
+ (st:deftest string-partition-as-expected-2 () |
|
24 |
+ (st:should be vos-equal |
|
25 |
+ '("b" "ad") |
|
26 |
+ (partition #(#\a) "baad"))) |
|
27 |
+ (st:deftest string-partition-as-expected-2-end () |
|
28 |
+ (st:should be vos-equal |
|
29 |
+ '("ba" "") |
|
30 |
+ (partition #(#\a #\d) "baad"))) |
|
31 |
+ (st:deftest string-partition-as-expected-2-begin () |
|
32 |
+ (st:should be vos-equal |
|
33 |
+ '("" "ad") |
|
34 |
+ (partition #(#\b #\a) "baad"))) |
|
35 |
+ |
|
36 |
+ |
|
37 |
+ (st:deftest string-partition-as-expected-3 () |
|
38 |
+ (st:should be vos-equal |
|
39 |
+ '("b" "ad") |
|
40 |
+ (partition #\a "baad"))) |
|
41 |
+ (st:deftest string-partition-as-expected-3-end () |
|
42 |
+ (st:should be vos-equal |
|
43 |
+ '("baa" "") |
|
44 |
+ (partition #\d "baad"))) |
|
45 |
+ (st:deftest string-partition-as-expected-3-begin () |
|
46 |
+ (st:should be vos-equal |
|
47 |
+ '("" "aad") |
|
48 |
+ (partition "b" "baad")))) |
|
49 |
+ |
|
8 | 50 |
(progn |
9 | 51 |
(st:deftest string-split-as-expected-with-test () |
10 | 52 |
(st:should be vos-equal |
... | ... |
@@ -99,7 +141,11 @@ |
99 | 141 |
(%split-on-char #\. "Bacon"))) |
100 | 142 |
) |
101 | 143 |
|
144 |
+#+nil |
|
102 | 145 |
(progn |
146 |
+ (unintern 'string-partition-as-expected-1) |
|
147 |
+ (unintern 'string-partition-as-expected-2) |
|
148 |
+ (unintern 'string-partition-as-expected-3) |
|
103 | 149 |
(unintern 'char-split-as-expected) |
104 | 150 |
(unintern 'char-split-as-expected-with-consecutive-sep) |
105 | 151 |
(unintern 'char-split-as-expected-with-test) |