Skip to content

Commit

Permalink
misc/list: add 'limit' argument to split procedure
Browse files Browse the repository at this point in the history
  • Loading branch information
Paradiesstaub committed Oct 28, 2019
1 parent fe1dc35 commit 28ca860
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 26 deletions.
16 changes: 8 additions & 8 deletions doc/reference/misc.md
Original file line number Diff line number Diff line change
Expand Up @@ -2254,23 +2254,23 @@ When `lst` is empty, `lst` is returned as it is.

### split
``` scheme
(split lst proc) -> list
(split lst proc [limit = #f]) -> list
lst := proper list
proc := unary procedure
lst := proper list
proc := unary procedure
limit := optional, split the list only limit times
```

split the list `lst` into a list-of-lists using the unary procedure `proc`.
If limit is set, split the list only `limit` times.

::: tip Examples:
``` scheme
(split '(1 2 "hi" 3 4) string?)
> ((1 2) (3 4))
(split '(1 2 a 3 4) (lambda (x) (equal? x 'a)))
> ((1 2) (3 4))
(split '(1 2 a 3 4) (cut equal? <> 'a))
> ((1 2) (3 4))
(split [1 2 0 3 4 0 5 6] zero? 1)
> ((1 2) (3 4 0 5 6))
(split [] number?)
> ()
Expand Down
8 changes: 7 additions & 1 deletion src/std/misc/list-test.ss
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,13 @@
(test-case "test split"
(check-equal? (split '(1 2 a 3 4) (cut equal? <> 'a)) [[1 2] [3 4]])
(check-equal? (split '(1 2 "hi" ()) string?) [[1 2] [[]]])
(check-equal? (split [] number?) []))
(check-equal? (split [] number?) [])
(check-equal? (split [1] number?) [[] []])
(check-equal? (split [1 2 0 3 4 0 5 6] zero?) [[1 2] [3 4] [5 6]])
(check-equal? (split [1 2 0 3 4 0 5 6] zero? 1) [[1 2] [3 4 0 5 6]])
(check-equal? (split [1 2 0 3 4 0 5 6] zero? 2) [[1 2] [3 4] [5 6]])
;; limit = 10 to tests the match else clause
(check-equal? (split [1 2 0 3 4 0 5 6] zero? 10) [[1 2] [3 4] [5 6]]))
(test-case "test group"
(check-equal? (group [1 2 2 3 1]) [[1] [2 2] [3] [1]])
(check-equal? (group []) [])
Expand Down
34 changes: 17 additions & 17 deletions src/std/misc/list.ss
Original file line number Diff line number Diff line change
Expand Up @@ -268,23 +268,23 @@
lst))

;; split the list lst into a list-of-lists using the unary procedure proc.
;; (split '(1 2 "hi" 3 4) string?) => ((1 2) (3 4))
;; (split '(1 2 a 3 4) (lambda (x) (equal? x 'a))) => ((1 2) (3 4))
;; (split '(1 2 a 3 4) (cut equal? <> 'a)) => ((1 2) (3 4))
;; (split [] number?) => ()
(def (split lst proc)
(def (new-acc acc cur)
(if (pair? cur) (cons* (reverse! cur) acc) cur))
(let loop ((cur []) (acc []) (lst lst))
(cond
((pair? lst)
(if (proc (car lst))
(loop [] (new-acc acc cur) (cdr lst))
(loop (cons (car lst) cur) acc (cdr lst))))
(else
(if (pair? cur)
(snoc (reverse! cur) acc)
acc)))))
;; If limit is set, split the list only limit times.
;;
;; Examples:
;; (split '(1 2 "hi" 3 4) string?) => ((1 2) (3 4))
;; (split [1 2 0 3 4 0 5 6] zero? 1) => ((1 2) (3 4 0 5 6))
;; (split [] number?) => ()
(def (split lst proc (limit #f))
(declare (fixnum))
(if (pair? lst)
(let loop ((xs lst) (acc []) (buf []) (n (if (fixnum? limit) limit -1)))
(match* ((zero? n) xs)
((#f [v . xs]) (if (proc v)
(loop xs (cons (reverse! buf) acc) [] (1- n))
(loop xs acc (cons v buf) n)))
((#t [v . xs]) (reverse! (cons (cons v xs) acc)))
(else (foldl cons [(reverse! buf)] acc))))
[]))

;; group consecutive elements of the list lst into a list-of-lists.
;;
Expand Down

0 comments on commit 28ca860

Please sign in to comment.