Reputation: 35
Is there a good way to filter a list using each element and its index in scheme? This is how I'm doing it now, but it seems overly complex
(map cdr
(filter (lambda (index-and-element)
(filter-proc (car index-and-element)
(cdr index-and-element)))
(map cons (iota (length l))
l)))
Upvotes: 1
Views: 146
Reputation: 71075
Looks perfectly fine to me. Except, perhaps you meant map cdr
...
Personally I like very short variable names whenever possible, so instead of index-and-element
I'd just use ie
-- they are unimportant, it's just some wiring, so make them as invisible as possible.
Another possibility is to use (map list ...)
initially, not (map cons ...)
, and then inside the lambda
to use (apply filter-proc ie)
. this way filter-proc
is called with two arguments, so it can be defined (define (filter-proc idx elt) ...)
.
And after all that, since it is indeed complex and error-prone to type all this anew each time, we'd just define a higher-order function for this so it is easier to use, like
(define (indexed-filter ipred lst)
(filter (lambda (ie)
(apply ipred ie))
(map list (iota (length lst))
lst)))
;; (define (ipred idx elt) ....) ; returns Bool
and use it whenever the need arises.
I've intentionally left out the (map cadr ...)
post-processing step, since you could sometimes want to get the indices of the matching elements instead of the elements themselves. So that would be part of the calling "protocol" so to speak -- whether you're interested in indices, elements, or both, you'd just tweak the call to this general procedure.
Upvotes: 1