Reputation: 3829
I have a nested foo
where each element is a bar
, and I'd like to flatten the foo
s without flattening the bar
s.
For example:
(special-flatten (foo (foo (bar 2) (bar 3)) (foo (bar 4) (bar 5)))) ;=>
((bar 2) (bar 3) (bar 4) (bar 5))
Using the normal flatten
from racket does not work, because I get (bar 2 bar 3 bar 4 bar 5)
.
foo
can be nested arbitrarily deep.
Is there a racket-y way to do this?
Upvotes: 0
Views: 208
Reputation: 8373
If you have a predicate that determines when a sublist shouldn't be flattened, then you can do this.
;; An Element is a value for which element? returns true
;; element? : Any -> Boolean
(define (element? v)
...you-have-to-determine-this...)
This element?
predicate should answer the question, "What determines when a sublist shouldn't be flattened?" In your case this means things that start with bar
such as (bar 2)
and (bar 3)
.
;; An Element is a (cons 'bar Any)
;; element? : Any -> Boolean
(define (element? v)
(and (pair? v) (equal? (car v) 'bar)))
Once this element?
predicate is defined, you can make a flatten function based on it:
;; A NestedFooListofElement is one of:
;; - Element
;; - (cons 'foo [Listof NestedFooListofElement])
;; foo-list? : Any -> Boolean
(define (foo-list? v)
(and (list? v) (pair? v) (equal? (car v) 'foo)))
;; special-flatten : NestedFooListofElement -> [Listof Element]
(define (special-flatten nfle)
(cond
[(element? nfle) (list nfle)]
[(foo-list? nfle) (append-map special-flatten (rest nfle))]))
Using it:
> (special-flatten '(foo (foo (bar 2) (bar 3)) (foo (bar 4) (bar 5))))
'((bar 2) (bar 3) (bar 4) (bar 5))
Upvotes: 1