展平Scheme中的关联列表

时间:2013-09-10 15:01:02

标签: list scheme

(define (associate lst)
    (if (or (null? lst) (= (length lst) 1))
        '()
        (cons (cons (car lst) (cadr lst)) (associate (cddr lst)))))

(define (disassociate lst)
    ;(display (caar lst))
    (if (null? lst)
        '()
        (cons (cons (caar lst) (cdar lst)) (disassociate (cdr lst)))))

(display (disassociate '((a . 1) (b . 2) (c . 3))))
(newline)
(display (associate '(a 1 b 2 c)))
(newline)

输出:

;; with list
((a 1) ((b 2) ((c 3) ())))
((a . 1) (b . 2))

;; with cons
((a . 1) (b . 2) (c . 3))
((a . 1) (b . 2))

我正试图在Scheme中括起一个关联列表,但是括号 即使我将list更改为cons,也会继续调高。我做错了吗?

2 个答案:

答案 0 :(得分:3)

您在disassociate中创建列表的方式有误。试试这个:

(define (disassociate lst)
  (if (null? lst)
      '()
      (cons (caar lst)
            (cons (cdar lst) 
                  (disassociate (cdr lst))))))

或者,使用list*

(define (disassociate lst)
  (if (null? lst)
      '()
      (list* (caar lst)
             (cdar lst) 
             (disassociate (cdr lst)))))

以上假设关联列表正在使用cons将值粘在一起,注意输出列表是如何通过cons第一个元素创建的,然后是第二个元素然后调用递归。另一方面,如果使用list创建关联列表以将值粘贴在一起,那么这就是解除它的方法:

(define (disassociate lst)
  (if (null? lst)
      '()
      (cons (caar lst)
            (cons (cadar lst) ; here's the change
                  (disassociate (cdr lst))))))

或者:

(define (disassociate lst)
  (if (null? lst)
      '()
      (list* (caar lst)
             (cadar lst) ; here's the change
             (disassociate (cdr lst)))))

更惯用的解决方案是使用更高阶的过程来处理输入列表。以下是使用foldr表示问题中描述的两个关联列表变体的方法:

; associations created with cons
(define (disassociate lst)
  (foldr (lambda (pr ac) (list* (car pr) (cdr pr) ac))
         '()
         lst))

; associations created with list
(define (disassociate lst)
  (foldr (lambda (pr ac) (list* (car pr) (cadr pr) ac))
         '()
         lst))

答案 1 :(得分:3)

您的disassociate行需要阅读:

(cons (caar lst) (cons (cdar lst) (disassociate (cdr lst)))))

准引用!有时这些使用准引用更清楚地实现,因为准引用可以让您看到结果列表结构。

(define (associate lst)
  (if (or (null? lst) (null? (cdr lst)))
       '()
       `(,(cons (car lst) (cadr lst)) ,@(associate (cddr lst)))))

(define (disassociate lst)
  (if (null? lst)
      '()
      `(,(caar lst) ,(cdar lst) ,@(disassociate (cdr lst)))))

> (associate (disassociate '((a . 1) (b . 2))))
((a . 1) (b . 2))

请注意,您还可以将associate准引用写为:

       `((,(car lst) . ,(cadr lst)) ,@(associate (cddr list)))))

但是对我来说开始变得越来越难以阅读,即使它使关联对显而易见。