Scheme从列表中提取唯一原子

时间:2013-06-30 01:29:55

标签: list scheme unique

我正在尝试编写一个scheme函数,它将返回在输入列表中找到的唯一原子。

> (unique-atoms '(a (b) b ((c)) (a (b))))
(a c b)
> (unique-atoms '(a . a))
(a)
> (unique-atoms '())
()

我在想这样的事情作为一个开始

(define (unique-atoms l)
  (if (null? l)
      '()
   (eq? (car (l) unique-atoms(cdr (l))))))

但我不知道如何收集唯一的原子,并在递归检查所有内容时创建一个新列表。

4 个答案:

答案 0 :(得分:1)

这个问题有两个部分:

  1. 您需要找到一种方法来访问给定表单的每个元素,并递归到子列表中。
  2. 您需要一种方法来收集所访问的唯一元素。
  3. 这是第一部分的解决方案:

    (define (recursive-fold visitor initial x)
      (let recur ((value initial)
                  (x x))
        (cond ((null? x) value)
              ((pair? x) (recur (recur value (car x)) (cdr x)))
              (else (visitor x value)))))
    

    我留给你实施第二部分。

答案 1 :(得分:1)

以下步骤list,按字词排除。如果next值本身就是一个列表,则会使用(append next rest)进行递归调用 - 也就是说,当list行走时,我们会同时展平子列表。

我们使用(尾部)递归函数looking来遍历列表并累积rslt。我们在next中没有rslt时添加到结果中。

(define (uniquely list)
  (let looking ((rslt '()) (list list))
    (if (null? list)
        rslt
        (let ((next (car list))
              (rest (cdr list)))
          (if (list? next)
              (looking rslt (append next rest))
              (looking (if (memq next rslt)
                           rslt
                           (cons next rslt))
                       rest))))))
> (uniquely '(a b (a b) ((((a))))))
(b a)

如果您确实希望代码适用于'(a . a)之类的“不正确的列表”,那么谓词null?list?可能需要更改。

答案 2 :(得分:0)

我找到了一个解决非唯一项目的半解决方案,虽然这不适用于原子b和带有b的列表,例如'(b(b))

(define (uniqueAtoms l)
  (cond ((null? l)
         '())
        ((member (car l) (cdr l))
         (uniqueAtoms (cdr l)))
        (else
         (cons (car l) (uniqueAtoms (cdr l))))))

答案 3 :(得分:-1)

使用各种列表结构解决此问题的最简单方法是将其分为两部分

1)展平然后列表 - 这会产生一个没有子列表的正确列表

; if you use Racket, you can use the build-in flatten procedure
; otherwise this one should do
(define (flatten expr)
  (let loop ((expr expr) (res '()))
    (cond 
      ((empty? expr) res)
      ((pair? expr)  (append (flatten (car expr)) (flatten (cdr expr))))
      (else          (cons expr res)))))

2)找到这个正确列表的所有独特成员

(define (unique-atoms lst)
  (let loop ((lst (flatten lst)) (res '()))
    (if (empty? lst)
        (reverse res)
        (let ((c (car lst)))
          (loop (cdr lst) (if (member c res) res (cons c res)))))))

试验:

; unit test - Racket specific
(module+ test
  (require rackunit)
  (check-equal? (unique-atoms '(a (b) b ((c)) (a (b)))) '(a b c))
  (check-equal? (unique-atoms '(a (b) b ((c . q)) (a (b . d)))) '(a b c q d))
  (check-equal? (unique-atoms '(a . a)) '(a))
  (check-equal? (unique-atoms '(a b (a b) ((((a)))))) '(a b))
  (check-equal? (unique-atoms '()) '()))