2012-05-13 35 views
3

我在LISP中完成了這項作業,我需要從中列出原子,然後列出子列表。我敢肯定,這應該是一件容易的事情,但由於我不是一個程序員,所以這真的需要我花很長時間才能理解。首先理清原子,然後從列表中列出LISP

我有一個數字這份名單:

(5 -1 (2 6 1) (8 7 -3) (0 (9 4)) -6) 

如果我理解正確的話我的任務那麼我應該得到的東西是這樣的:

(5 -1 -6 (2 6 1) (8 7 -3) (0 (9 4))) 

到目前爲止,所有我發現了是怎麼算原子和/或子列表,但我不需要那個。

(DEFUN ATOMNUMBER (L) (COND ((NULL L) 0) 
    ((ATOM (CAR L)) (+ 1 (ATOMNUMBER (CDR L)))) 
    (T (ATOMNUMBER (CDR L))))) 

此外,即使只有子列表,只有原子或只是空列表,函數應該正常工作。

也許有人可以給我任何例子?

在此先感謝!

回答

2

我更習慣於計劃,但這裏是在Lisp的有效的解決方案:

(defun f (lst) 
    (labels 
     ((loop (lst atoms lists) 
     (cond 
      ((null lst) 
      (append (reverse atoms) (reverse lists))) 
      ((atom (car lst)) 
      (loop (cdr lst) (cons (car lst) atoms) lists)) 
      (T 
      (loop (cdr lst) atoms (cons (car lst) lists)))))) 
    (loop lst '() '()))) 

(f '(5 -1 (2 6 1) (8 7 -3) (0 (9 4)) -6)) 

基本上你迭代列表,每個元素都是eit她被添加到原子列表或列表列表中。最後你們加入這兩個來獲得你的結果。

編輯

刪除,如果版本是這樣短,當然,:

(let ((l '(5 -1 (2 6 1) (8 7 -3) (0 (9 4)) -6))) 
    (append 
    (remove-if-not #'atom l) 
    (remove-if  #'atom l))) 
+0

謝謝,這個作品完美。 – user1392317

+0

你能舉個例子,我應該在第一個代碼中編輯什麼,以便它能夠對矩陣中的原子進行排序?例如,我有(((4 5)2)(3(2)5)(4(0)2 6)),它應該像這樣排序原子:((2(4 5))(3 5(2) )(4 2 6(0))) – user1392317

+1

Try(mapcar#'f(((4 5)2)(3(2)5)(4(0)2 6)))。 – uselpa

7

有Common Lisp中的幾種可能的方法:

  • 使用REMOVE-IF刪除不需要的項目。 (或者使用REMOVE-IF-NOT來保留想要的項目。)您需要兩個列表。追加它們。

  • 使用DOLIST和遍歷列表,收集的內容分爲兩個列表和添加他們

  • 寫到哪,你需要保持兩個結果列表遞歸過程。

  • 也應該可以使用SORT和特殊排序謂詞。

例子:

> (sort '(1 (2 6 1) 4 (8 7 -3) 4 1 (0 (9 4)) -6 10 1) 
     (lambda (a b) 
      (atom a))) 

(1 10 -6 1 4 4 1 (2 6 1) (8 7 -3) (0 (9 4))) 

穩定的版本:

(stable-sort '(1 (2 6 1) 4 (8 7 -3) 4 1 (0 (9 4)) -6 10 1) 
      (lambda (a b) 
       (and (atom a) 
        (not (atom b))))) 

(1 4 4 1 -6 10 1 (2 6 1) (8 7 -3) (0 (9 4))) 
+0

謝謝,這將幫助我在我的下一個任務(類似於第一個)。 – user1392317

+0

也許最好保留原來的順序;但是通過這個謂詞,即使'stable-sort'返回的結果與sort相同。 –

0

這裏是一個反覆的代碼,以自上而下的方式構建其輸出(註釋是在Haskell語法):

;atomsFirst xs = separate xs id id where 
; separate [] f g = f (g []) 
; separate (x:xs) f g 
;  | atom x = separate xs (f.(x:)) g 
;  | True = separate xs f (g.(x:)) 

(defmacro app (l v) 
    `(progn (rplacd ,l (list ,v)) (setq ,l (cdr ,l)))) 

(defun atoms-first (xs) 
    (let* ((f (list nil)) (g (list nil)) (p f) (q g)) 
    (dolist (x xs) 
     (if (atom x) (app p x) (app q x))) 
    (rplacd p (cdr g)) 
    (cdr f))) 

以自頂向下方式構建的兩個中間列表被維護爲開放式li sts(即帶有明確的結束指針),基本上遵循差異列表範例。

0

以防萬一,你會想多鍛鍊,你會發現,這裏提供的例子是不夠的:P

(defun sort-atoms-first-recursive (x &optional y) 
    (cond 
    ((null x) y) 
    ((consp (car x)) 
    (sort-atoms-first-recursive (cdr x) (cons (car x) y))) 
    (t (cons (car x) (sort-atoms-first-recursive (cdr x) y))))) 

(defun sort-atoms-first-loop (x) 
    (do ((a x (cdr a)) 
     (b) (c) (d) (e)) 
     (nil) 
    (if (consp (car a)) 
     (if b (setf (cdr b) a b (cdr b)) (setf b a d a)) 
     (if c (setf (cdr c) a c (cdr c)) (setf c a e a))) 
    (when (null (cdr a)) 
     (cond 
     ((null d) (return e)) 
     ((null c) (return d)) 
     (t (setf (cdr b) nil (cdr c) d) (return e)))))) 


(sort-atoms-first-recursive '(5 -1 (2 6 1) (8 7 -3) (0 (9 4)) -6)) 

(sort-atoms-first-loop '(5 -1 (2 6 1) (8 7 -3) (0 (9 4)) -6)) 

第二個是破壞性的(但不建立任何新的conses之外) 。

0

你可以做到這一點遞歸的方式:

(defun f (lst) 
    (cond 
     ((null lst) nil) 
     ((atom (car lst)) 
     (append (list (car lst)) (f (cdr lst)))) 
     (T 
      (append (f (cdr lst)) (list (f (car lst)))) 
     ) 
    ) 
) 
(step (f '(5 -1 (2 6 1) (8 7 -3) (0 (9 4)) -6))) 

輸出:

step 1 --> (F '(5 -1 (2 6 1) (8 7 -3) ...))                 
step 1 ==> value: (5 -1 -6 (0 (9 4)) (8 7 -3) (2 6 1)) 
相關問題