列表中相同原子元素的数量,如 (a (a b) (b c))

Number of same atomic elements in a list like (a (a b) (b c))

我想向您寻求以下帮助:

当我在列表上应用程序元素数时,我需要得到一个对列表,其中对中的第一位是元素,第二位(点之后)是元素是列表中出现的元素数。

例如,键入此内容时:

(number-of-elements '((a b c) a (b c) c (a b b)))

我知道了:

((a . 3) (b . 4) (c . 3))

到目前为止,我有一个代码可以处理常规列表 (a b a d)。

(define number-of-elements
 (lambda (lst)
  (define exclude
  (lambda (sznm key)
    (foldr (lambda (ass result)
             (if (equal? (car ass) key)
                 result
                 (cons ass result)))
           '()
           sznm)))
(foldr (lambda (key bag)
         (cond ((assoc key bag)
                => (lambda (old)
                     (let ((new (cons key (+ (cdr old) 1))))
                       (cons new (exclude bag key)))))
               (else (let ((new (cons key 1)))
                       (cons new bag)))))
       '()
       lst)))

但是如果我用在:

(number-of-elements '((a b c) a (b c) c (a b b)))

我知道了:

(((a b c) . 1) (a . 1) ((b c) . 1) (c . 1) ((a b b) . 1))

我知道我需要使用深度递归,但我不知道如何将它实现到我实际拥有的代码中。

您已经完成了计算元素的大部分工作 - 但请参阅 bagify 的不同实现以获得更简单的实现。处理嵌套子列表的一种直接解决方案是在计算元素之前 flatten 输入列表:

(number-of-elements
 (flatten
  '((a b c) a (b c) c (a b b))))

=> '((a . 3) (b . 4) (c . 3))

如果你的解释器没有定义flatten,很容易实现:

(define (flatten lst)
  (if (not (list? lst))
      (list lst)
      (apply append (map flatten lst))))

这是在 Scheme 中思考解决方案的惯用方法:将问题分解成多个部分,然后使用 built-in 过程来解决每个子部分,最后将它们组合起来。