2014-09-24 84 views
0

中列表遍歷myList是一個列表,其元素既可以是符號,也可以是具有相同類型myList的列表。例如:myList ='(a b(a d c)d())等。在方案

我想在Scheme中編寫一個函數,它只是遍歷它(最終我會用其他值替換符號)。

我寫了這個功能:

(define traversal (lambda (myList) 
     (if (null? myList) '() 
      (if (and (list? (car myList)) (not (null? (car myList)))) 
       (list (traversal (car myList)) (traversal (cdr myList))) 
       ; else if car is an empty list 
       (if (null? (car myList)) 
        (list (traversal (cdr myList))) 
        ; else car is a symbol 
        (append (list (car myList)) (traversal (cdr myList)))))))) 

它給出了myList中的一些配置正確的結果,但肯定它不是一個。 例如,

(display (traversal '((f) h (r t b) (x m b m y) b (c (d))))) 

增加了我不需要的額外參數。

什麼是正確的方式來顯示這樣的列表?

回答

1
  1. 您在很多地方測試null?,其中一次測試通常就足夠了。
  2. 在這些遍歷中,您很少使用list,但只需cons即可。
  3. 此外,append是最好的避免,這裏不需要。
  4. 重複使用(car ...)let形式進行了優化。

代碼的簡化形式是:

(define traversal 
    (lambda (myList) 
    (if (null? myList) 
     '() 
     (let ((c (car myList))) 
      (cons (if (list? c) (traversal c) c) 
       (traversal (cdr myList))))))) 

編輯

雖然這個過程非常適用於正確的列表,它不能正常不當列出工作(儘管它似乎)。以下是對每一種S-expression,包括適當的工作列出一個更通用的方法,我建議這個比以前的代碼:

(define traversal 
    (lambda (sexp) 
    (cond 
     ((null? sexp) '()) 
     ((pair? sexp) (cons (traversal (car sexp)) 
          (traversal (cdr sexp)))) 
     (else   sexp)))) 
+0

真的謝謝多少爲這個! – Madrugada 2014-09-24 21:35:58

+0

不客氣! – uselpa 2014-09-24 21:41:59

+0

既然你使用'list?',那麼首選而不是'first'和'rest'而不是'car'和'cdr'? (因爲它顯然是'#!racket'代碼) – Sylwester 2014-09-24 22:33:49

1

您已接近解決方案。以下是一些提示:

而不是嵌套if s嘗試使用cond窗體,它更具可讀性。

表達式(and (list? (car myList)) (not (null? (car myList))))是正確的,但是您可以使用(pair? (car myList)),它更短且幾乎完成相同的操作。

traversal應該返回一個列表,但使用list與在此列出的參數 (list (traversal (car myList)) (traversal (cdr myList))) 將返回一個列表的列表。例如。 (list '(a) '(b))將返回((a) (b))而不是(a b)。在這些情況下,您應該使用append(append '(a) '(b)) - >(a b)

如果某個值不是一個列表,而是想將其添加到現有列表中,請使用cons過程。 (cons 'a '(b c)) - >(a b c)