Я пытаюсь создать for
l oop, который перебирает список чисел и печатает каждое третье число.
Обычно более полезно создать новый список с желаемыми значениями, а затем распечатать эти значения, передать их функции или выполнить все, что может понадобиться. for/list
действительно возвращает список, и это одна из причин проблем, встречающихся в примере кода OP. (Другие проблемы в OP-коде включают в себя то, что x
- это число с [x (in-range 20)]
, поэтому (cdr x)
не определено).
Возможным решением будет повторение по списку ввода с использованием take
чтобы получить следующие три значения, оставив третье и используя drop
, чтобы уменьшить список ввода:
;; Recurse using `take` and `drop`:
(define (every-3rd-1 lst)
(if (< (length lst) 3)
'()
(cons (third (take lst 3))
(every-3rd-1 (drop lst 3)))))
Другой вариант - выполнить рекурсию в списке ввода с помощью вспомогательного счетчика; начиная с 1, сохраняйте значения из списка ввода только тогда, когда счетчик кратен 3:
;; Recurse using an auxilliary counter:
(define (every-3rd-2 lst)
(define (every-3rd-helper lst counter)
(cond [(null? lst)
'()]
[(zero? (remainder counter 3))
(cons (first lst) (every-3rd-helper (rest lst) (add1 counter)))]
[else (every-3rd-helper (rest lst) (add1 counter))]))
(every-3rd-helper lst 1))
Еще одной возможностью будет использование for/list
для построения списка; здесь i
привязано к значениям из списка ввода, а counter
привязано к значениям из списка счетных чисел:
;; Use `for/list` to build a list:
(define (every-3rd-3 lst)
(for/list ([i lst]
[counter (range 1 (add1 (length lst)))]
#:when (zero? (remainder counter 3)))
i))
Эта функция (или любая из них, в этом отношении) может быть обобщенно полезным для хранения каждого n-го элемента:
;; Generalize to `every-nth`:
(define (every-nth n lst)
(for/list ([i lst]
[counter (range 1 (add1 (length lst)))]
#:when (zero? (remainder counter n)))
i))
Наконец, map
может использоваться для создания списка, содержащего каждый n-й элемент, путем сопоставления диапазона каждого n-го индекса в списке:
;; Use `map` and `range`:
(define (every-nth-map n lst)
(map (lambda (x) (list-ref lst x)) (range (sub1 n) (length lst) n)))
Если в действительности OP требует просто напечатать каждое третье значение, а не создавать список каждого третьего значения, возможно, приведенный выше код может предоставить полезные материалы, позволяющие OP прийти к удовлетворительному выводу. Но каждая из этих функций также может использоваться для вывода результатов в виде желаний OP:
scratch.rkt> (for ([x (every-3rd-1 '(a b c d e f g h i j k l m n o p))])
(displayln x))
c
f
i
l
o
scratch.rkt> (for ([x (every-3rd-2 '(a b c d e f g h i j k l m n o p))])
(displayln x))
c
f
i
l
o
scratch.rkt> (for ([x (every-3rd-3 '(a b c d e f g h i j k l m n o p))])
(displayln x))
c
f
i
l
o
scratch.rkt> (for ([x (every-nth 3 '(a b c d e f g h i j k l m n o p))])
(displayln x))
c
f
i
l
o
scratch.rkt> (for ([x (every-nth-map 3 '(a b c d e f g h i j k l m n o p))])
(displayln x))
c
f
i
l
o