scheme - 检查元素是否出现在表达式或其任何嵌套表达式中两次或更多次的函数

scheme - function that checks whether an element appears in an expression or any of its nested expressions twice or more

我编写了以下函数来检查 el 是否出现在 exp 或其任何嵌套列表中 一次 或更多,但我无法理解如何检查 两次:

(define appearInExp?
    (lambda (el exp)
        (let ((found?     (ormap (lambda (e) (equal? el e)) exp))
              (listsLeft? (ormap (lambda (e) (list? e)) exp))
              (lists (filter (lambda (e) (list? e)) exp)))

        (if found?
            #t
            (if (not listsLeft?)
                #f
                (let ((elList (extendList el (length lists))))
                    (ormap appearInExp? elList lists)))))))



  *help function:*

    (define extendList
        (lambda (el num)
            (if (equal? num 1)
                `(,el)
                `(,el ,@(extendList el (- num 1))))))

**tests:
(appearInExp? '3 '(1 2 3))             ---> #t
(appearInExp? '3 '(1 2 '(3)))          ---> #t
(appearInExp? '3 '(1 2 '(1 2 ((3)))))  ---> #t

我想我应该添加计数器并让每个递归调用计算相关 exp 中有多少个 el 实例并将它们加在一起,但我这样做时遇到了麻烦..

非常感谢您的帮助。

以下作品。它有一个计数器 c 和一个遍历列表所有项目的循环。如果该项是一个列表,函数被递归调用:

(define (appearInExp? el exp)
  (let loop ((exp exp)
             (c 0))
    (cond
      [(empty? exp) c]
      [(list? (first exp))
       (loop (rest exp)
             (+ c (appearInExp? el (first exp))))]
      [(equal? el (first exp))
       (loop (rest exp) (add1 c))]
      [else
       (loop (rest exp) c)])))

(appearInExp? '2 '(1 2 3))
(appearInExp? '2 '(1 2 '(2 3)))
(appearInExp? '2 '(1 2 '(1 2 ((3 2)))))

输出:

1
2
3

您可以采用的另一种方法是展平列表。

(define (flatten lst)
  (cond [(empty? lst) empty]
        [(number? (first lst)) (cons (first lst) (flatten (rest lst)))]
        [else (append (flatten (first lst)) (flatten (rest lst)))]))

(define (f/acc n lst counter)
  (cond [(empty? lst) counter)]
        [(= n (first lst)) (f n lst (add1 counter))]
        [else (f n lst counter)]))

(define (f n lst)
   (f/acc n lst 0))