【问题标题】:To sort out atoms first and then sublists from a list in LISP首先对原子进行排序,然后从 LISP 中的列表中进行子列表
【发布时间】:2012-05-21 08:03:37
【问题描述】:

我在 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))) ))

即使只有子列表、原子或空列表,该函数也应该能正常工作。

也许有人可以给我一些例子吗?

提前致谢!

【问题讨论】:

    标签: lisp common-lisp difference-lists


    【解决方案1】:

    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)))
    

    【讨论】:

    • 谢谢,这将帮助我完成下一个任务(类似于第一个任务)。
    • 也许希望保留原始顺序;但是有了这个谓词,即使stable-sort 也会返回与sort 相同的结果。
    【解决方案2】:

    我更习惯于 Scheme,但这里有一个适用于 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))
    

    基本上你遍历列表,每个元素要么附加到原子列表或列表列表。最后你加入两者以获得你的结果。

    编辑

    当然,remove-if 版本要短得多:

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

    【讨论】:

    • 您能否举个例子,我应该在第一个代码中编辑什么,以便对矩阵中的原子进行排序?例如我有 (((4 5) 2)(3 (2) 5)(4 (0) 2 6)) 它应该像这样对原子进行排序: ((2 (4 5))(3 5 (2) )(4 2 6 (0)))
    • 试试 (mapcar #'f (((4 5) 2)(3 (2) 5)(4 (0) 2 6)))。
    • 不客气。只需确保您真正了解 为什么 它会起作用。如果没有,请不要犹豫再问一次。
    【解决方案3】:

    这是一个迭代代码,以自上而下的方式构造其输出(注释为 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)))
    

    以自上而下的方式构建的两个中间列表被维护为开放式列表(即具有显式结束指针),基本上遵循差异列表范式。

    【讨论】:

      【解决方案4】:

      以防万一你想多运动,你会发现这里提供的例子还不够: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)。

      【讨论】:

        【解决方案5】:

        你可以这样做递归方式:

        (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))
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-06-28
          • 2011-02-17
          • 2018-05-30
          • 2014-09-22
          • 1970-01-01
          • 2014-03-17
          • 2023-03-13
          相关资源
          最近更新 更多