123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- (library (list-helpers)
- (export flatten
- make-list
- split-off-n
- split-into-n-sized-segments
- split-at
- split-into-segments
- split-into-n-segments)
- (import
- (except (rnrs base) let-values map error)
- (only (guile)
- lambda* λ
- remainder
- round
- simple-format)
- ;; receive form
- (srfi srfi-8))
- (define flatten
- (λ (lst)
- (cond [(null? lst) '()]
- [(pair? lst)
- (append (flatten (car lst))
- (flatten (cdr lst)))]
- [else
- (list lst)])))
- (define make-list
- (λ (val count)
- (cond
- [(> count 0)
- (cons val (make-list val (- count 1)))]
- [else '()])))
- (define split-off-n
- (λ (lst n)
- "Take a list LST and split off the first N elements. Return
- 2 values: The split off part and the remaining part of the
- list LST."
- (let iter ([lst° lst]
- [counter 0]
- [cont
- (λ (acc-split-off rem-lst)
- (values acc-split-off rem-lst))])
- (cond
- [(null? lst°)
- (cont '() lst°)]
- [(= counter n)
- (cont '() lst°)]
- [else
- (iter (cdr lst°)
- (+ counter 1)
- (λ (new-tail rem-lst)
- (cont (cons (car lst°) new-tail)
- rem-lst)))]))))
- (define split-into-n-sized-segments
- (λ (lst n)
- (cond
- [(null? lst) '()]
- [else
- (receive (split-off-part remaining-list)
- (split-off-n lst n)
- (cons split-off-part
- (split-into-n-sized-segments remaining-list n)))])))
- (define split-at
- (λ (lst pred)
- "Each element of LST is checked using the predicate. If the
- predicate is satisfied for an element, then that element
- will be seen as the separator. Return 2 values: The split
- off part and the remaining part of the list LST."
- (let iter ([lst° lst]
- [index° 0]
- [cont
- (λ (acc-split-off rem-lst)
- (values acc-split-off rem-lst))])
- (cond
- [(null? lst°)
- (cont '() lst°)]
- [(pred (car lst°) index°)
- (cont '() (cdr lst°))]
- [else
- (iter (cdr lst°)
- (+ index° 1)
- (λ (new-tail rem-lst)
- (cont (cons (car lst°) new-tail)
- rem-lst)))]))))
- (define split-into-segments
- (λ (lst pred)
- "Split the list LST into segments based on a predicate for
- an element being a separator or not. Each element is checked
- using the predicate. If the predicate is satisfied for an
- element, then that element will be seen as a separator and
- will not be part of the resulting segments."
- (cond
- [(null? lst) '()]
- [else
- (receive (split-off-part remaining-list) (split-at lst pred)
- (cons split-off-part
- (split-into-segments remaining-list pred)))])))
- (define split-into-n-segments
- (λ (lst n)
- "Try to split list LST into N segments. The function tries
- to make the segments as evenly sized as possible."
- (let ([chunk-size (round (/ (length lst) n))])
- (let iter ([lst° lst] [counter 0])
- (cond
- [(= counter (- n 1)) (list lst°)]
- [(and (< counter n) (null? lst°))
- (cons '() (iter lst° (+ counter 1)))]
- [(null? lst°) '()]
- [else
- (receive (split-off-part remaining-list) (split-off-n lst° chunk-size)
- (cons split-off-part
- (iter remaining-list (+ counter 1))))]))))))
|