2015-10-04 71 views
1

我是新来的计划,我试图编写一个过程,它将n列表合并到列表中n -tuples。如果列表的大小不同,则元组应包含空列表(),而相应列表的元素不足。变元列表填充空列表

我目前实行的是以下几点:

(define (comb list1 list2) 
    (cond [(empty? list1) empty] 
      [(empty? list2) empty] 
      [else (cons (list (first list1) (first list2)) 
         (comb (rest list1) (rest list2)))])) 

不过,这一方案时,有列表中没有更多的项目不产生另一元组相结合。例如,(comb '(1 2 3) '(3 4))只生产((1 3) (2 4))

我该如何解决?

回答

2

这有点棘手,我相信对于刚刚学习该语言的基础知识的人来说这不是一个适当的练习。无论如何,这是我提出的解决方案,在高阶程序方面:

; helper procedure for filling a list with arbitrary values at the end 
(define (fill lst val num) 
    (append lst 
      (build-list num (const val)))) 

; helper procedure for transposing a list of lists  
(define (transpose lsts) 
    (apply map list lsts)) 

; main procedure 
(define (list-tuples lsts) 
    (let* ((lengths (map length lsts)) ; obtain the length of each sublist 
     (max-length (apply max lengths))) ; find out the maximum length 
    (transpose        ; build new sublists element-wise 
    (map (lambda (lst len)    ; build sublists of the right length 
      (fill lst '() (- max-length len))) ; fill sublists with '() 
      lsts 
      lengths)))) 

诀窍是找到列表的最大长度,然后与长建新的列表,在结束与'()填充。之后,通过从每个子列表中取一个元素来构建答案是一件简单的事情。它按预期工作:

(list-tuples '((m n o) (1) (x y))) 
=> '((m 1 x) (n() y) (o()())) 
0

您需要特别处理其中一个列表为空的情况。以下是我认为你想要的两个列表。

(define (comb l1 l2) 
    (cond 
    ((empty? l1) 
     (cond 
     ((empty? l2) '()) 
     (else (cons (list '() (car l2)) (comb l1 (cdr l2)))))) 
    (else 
     (cond 
     ((empty? l2) (cons (list (car l1) '()) (comb (cdr l1) l2))) 
     (else (cons (list (car l1) (car l2)) (comb (cdr l1) (cdr l2)))))))) 
0

让我们把问题分成两部分。

首先,让我们假设将列表中的程序,并返回结果如下:

  1. 含各子表
  2. 包含的每个子表的剩余列表的第一项的列表
  3. 非空列表的数目遇到

示例实现可能是:

(define (split-tuples lst) 
    (let loop ((lst lst) (fst null) (rst null) (cnt 0)) 
    (if (null? lst) 
     (values (reverse fst) (reverse rst) cnt) 
     (let ((c (car lst))) 
      (if (null? c) 
       (loop (cdr lst) (cons  c fst) (cons  c rst) cnt) 
       (loop (cdr lst) (cons (car c) fst) (cons (cdr c) rst) (add1 cnt))))))) 

测试:

> (split-tuples '((m n o) (1) (x y))) 
'(m 1 x) 
'((n o)() (y)) 
3 
> (split-tuples '((n o)() (y))) 
'(n() y) 
'((o)()()) 
2 
> (split-tuples '((o)()())) 
'(o()()) 
'(()()()) 
1 
> (split-tuples '(()()())) 
'(()()()) 
'(()()()) 
0 

现在用这个过程中,我们创建的主要过程,将只是循环,直到所有子列表为空:

(define (list-tuples lst) 
    (let loop ((lst lst) (res null)) 
    (let-values (((fst rst cnt) (split-tuples lst))) 
     (if (zero? cnt) 
      (reverse res) 
      (loop rst (cons fst res)))))) 

测试:

> (list-tuples '((m n o) (1) (x y))) 
'((m 1 x) (n() y) (o()())) 
> (list-tuples '()) 
'()