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

时间:2016-01-16 22:21:37

标签: recursion numbers scheme

我想请求您提供以下帮助:

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

例如,输入时:

(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))

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

1 个答案:

答案 0 :(得分: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中解决方案的惯用方法:分解部分问题,然后使用内置程序解决每个子部分,最后将它们组合起来。