2015-10-04 114 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 '()) 
'()