Is there a way to filter by index in mit-scheme?

45 views Asked by At

I'm working through 99 scheme problems and I have a solution for P16 (Drop every N'th element from a list.) using recursion, but I'm trying to practice more functional methods. Is there a clean way to filter by index in mit-scheme?

(display (drop '(a b c d e f g h i j k) 3)))
=> (a b d e g h k)

In Python I could use enumerate:

import string
lst = list(string.ascii_lowercase[:11])
fltr = filter(lambda item: (item[0]+1)%3, enumerate(lst))
mp = map(lambda item: item[1], fltr)
print(list(mp))
=> ['a', 'b', 'd', 'e', 'g', 'h', 'j', 'k']

or list comprehensions

print([value for index, value in enumerate(lst) if (index+1)%3])
=> ['a', 'b', 'd', 'e', 'g', 'h', 'j', 'k']

Thanks!

2

There are 2 answers

0
Dinay Kingkiller On

My solution using @Dogbert 's hint about zip.

;; P16 (**) Drop every n'th element from a list.                                                         
; Example:                                                                                               
; * (drop '(a b c d e f g h i k) 3)                                                                      
; (a b d e g h k)

(define (drop lst n)
  (map (lambda (x) (cadr x))
       (filter (lambda (x) (not (equal? (modulo (+ 1 (car x)) n) 0)))
               (zip (iota (length lst)) lst))))

(display "P16: (drop '(a b c d e f g h i k) 3)\n")
(display (drop '(a b c d e f g h i k) 3))
1
alinsoar On
(define drop-each-nth
  (lambda (l n)
    ((lambda (s) (s s l (- n 1) (lambda (x) x)))
     (lambda (s l* k ret)
       (cond ((null? l*)
              (ret '()))
             ((zero? k)
              (s s (cdr l*)
                 (- n 1)
                 (lambda (x)
                   (ret x))))
             (else
              (s s (cdr l*)
                 (- k 1)
                 (lambda (x)
                   (ret (cons (car l*) x))))))))))

(drop-each-nth '(a b c d e f g h i j k) 3)