add `slicef-after`

pull/2/head
Matthew Butterick 10 years ago
parent b987bacfe4
commit 4cb7cfbc55

@ -9,6 +9,7 @@
(define (list-of-lists? xs) (and (list? xs) (andmap list? xs))) (define (list-of-lists? xs) (and (list? xs) (andmap list? xs)))
(define+provide/contract (slicef-at xs pred [force? #f]) (define+provide/contract (slicef-at xs pred [force? #f])
((list? procedure?) (boolean?) . ->* . list-of-lists?) ((list? procedure?) (boolean?) . ->* . list-of-lists?)
(define-values (last-list list-of-lists) (define-values (last-list list-of-lists)
@ -25,6 +26,19 @@
(cdr list-of-lists) (cdr list-of-lists)
list-of-lists))) list-of-lists)))
(define+provide/contract (slicef-after xs pred)
(list? procedure? . -> . list-of-lists?)
(define-values (last-list list-of-lists)
(for/fold ([current-list empty][list-of-lists empty])([x (in-list xs)])
(if (pred x)
(values empty (cons (reverse (cons x current-list)) list-of-lists))
(values (cons x current-list) list-of-lists))))
(reverse (if (empty? last-list)
list-of-lists
(cons (reverse last-list) list-of-lists))))
(define+provide/contract (slice-at xs len [force? #f]) (define+provide/contract (slice-at xs len [force? #f])
((list? (and/c integer? positive?)) (boolean?) . ->* . list-of-lists?) ((list? (and/c integer? positive?)) (boolean?) . ->* . list-of-lists?)
(define-values (last-list list-of-lists) (define-values (last-list list-of-lists)
@ -36,10 +50,7 @@
list-of-lists list-of-lists
(cons (reverse last-list) list-of-lists)))) (cons (reverse last-list) list-of-lists))))
;; this function could possibly be implemented as a post-processing step on slicef-at:
;; every list after the first list starts with an element matching pred.
;; so drop the first element from all lists except the first.
;; (cons (car xs) (map cdr (cdr xs)))
(define+provide/contract (filter-split xs pred) (define+provide/contract (filter-split xs pred)
(list? predicate/c . -> . list-of-lists?) (list? predicate/c . -> . list-of-lists?)
(define-values (last-list list-of-lists) (define-values (last-list list-of-lists)
@ -72,7 +83,6 @@
[else (error (format "members-unique? cannot be determined for ~a" x))])) [else (error (format "members-unique? cannot be determined for ~a" x))]))
(define+provide/contract (members-unique?/error x) (define+provide/contract (members-unique?/error x)
(any/c . -> . boolean?) (any/c . -> . boolean?)
(define result (members-unique? x)) (define result (members-unique? x))

@ -65,9 +65,22 @@ Divide @racket[_lst] into sublists starting with elements matching @racket[_pred
@examples[#:eval my-eval @examples[#:eval my-eval
(slicef-at (range 5) even?) (slicef-at (range 5) even?)
(slicef-at '(1 2 2 1 2) even?) (slicef-at '(1 2 2 1 2) even?)
(slicef-at '(1 2 2 1 2) even? #t)
(slicef-at (range 5) odd?) (slicef-at (range 5) odd?)
(slicef-at (range 5) odd? #t)] (slicef-at (range 5) odd? #t)]
@defproc[
(slicef-after
[lst list?]
[pred procedure?])
(listof list?)]
Divide @racket[_lst] into sublists ending with elements matching @racket[_pred]. (Distinct from @racket[slicef-at], which gives you sublists that @italic{start} with elements matching @racket[_pred].) If none of the elements match @racket[_pred], there is no slice to be made, and the result is the whole input list.
@examples[#:eval my-eval
(slicef-after '(1 2 2 1 2) even?)
(slicef-after (range 5) odd?)
(slicef-after (range 5) string?)]
@defproc[ @defproc[
(frequency-hash (frequency-hash
@ -132,6 +145,8 @@ Convert @racket[_values] to a simple list.
list?] list?]
Return a sublist of the @racket[_lst] starting with item @racket[_start-idx] and ending one item @bold{before} item @racket[_end-idx]. (Similar to how list slices are denominated in Python.) Thus the maximum value for @racket[_end-idx] is @racketfont{(length @racket[_lst])}. Errors will be triggered by nonsensical values for @racket[_end-idx]. Return a sublist of the @racket[_lst] starting with item @racket[_start-idx] and ending one item @bold{before} item @racket[_end-idx]. (Similar to how list slices are denominated in Python.) Thus the maximum value for @racket[_end-idx] is @racketfont{(length @racket[_lst])}. Errors will be triggered by nonsensical values for @racket[_end-idx].
Bear in mind that @racket[sublist] is built for convenience, not performance. If you need to do a lot of random access into the middle of an ordered sequence of items, you'd be better off putting them into a @racket[vector] and using @racket[vector-copy].
@examples[#:eval my-eval @examples[#:eval my-eval
(sublist '(0 1 2 3 4 5 6 7 8) 0 8) (sublist '(0 1 2 3 4 5 6 7 8) 0 8)
(sublist '(0 1 2 3 4 5 6 7 8) 8 9) (sublist '(0 1 2 3 4 5 6 7 8) 8 9)

Loading…
Cancel
Save