2012-05-13 39 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)) 
相关问题