Для l oop, который печатает каждый третий номер - PullRequest
1 голос
/ 30 марта 2020

Я пытаюсь создать для l oop, который перебирает список чисел и печатает каждое третье число.

Редактировать: я только понял, как использовать для l oop, но я не совсем уверен, есть ли конкретная функция c, которую я могу использовать, чтобы показывать только каждое третье число. Мне кажется, что я могу быть на правильном пути при использовании функции car / cdr, за исключением того, что я получаю ошибку

rest: ожидается нарушение контракта: (и / c список? (Не / *) 1015 * пусто?)) Дано: 0

Мой код:

(for/list ([x (in-range 20)] #:when (car(cdr(cdr x)))) (displayln x))

Ответы [ 2 ]

2 голосов
/ 31 марта 2020

Я пытаюсь создать 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
0 голосов
/ 30 марта 2020

Вот шаблон:

(for ([x (in-list xs)]
      [i (in-naturals]
   #:when some-condition-involving-i)
  (displayln x))
...