Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
255 views
in Technique[技术] by (71.8m points)

How to order a list in sublists in Lisp?

I have a list like this:

(4 5 6 3 12 22 4 4 55 43 1 4 0) 

and want an output like this:

((4 5 6) (3) (12 22) (4) (4 55) (43) (1 4) (0)) 

I think you can guess the order, it has an ascending order, I'm totally new with Lisp and need some help

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Here is one possible solution in TXR Lisp:

(defun ascending-partitions (list)
  (let ((indices (mappend (do if (>= @1 @2) (list @3))
                          list (cdr list) (range 1))))
    (split list indices)))

We obtain the numeric index positions of the elements in the list which are not greater than their predecessors; then we use the split function to cut the list into pieces at these indices.

Calculating the indices is done by processing three lists through the mappend function: the original list, in parallel with that same list with the first element removed (cdr list), and an infinite list of incrementing integers starting at 1 produced by (range 1).

The do macro writes an anonymous function for us, in which the @1, @2 and @3 variables embedded in the expression are its three arguments, in that order. mappend call this function with successive triplets of values taken from the lists in parallel. Thus @1 takes values from list, @2 takes successive values from (cdr list) and @3 takes successive values from the list of integers. Whenever @1 is at least as large as its successor @2, we collect the positional index @3 into a one-element list. mappend catenates these together.

In contrast to this, we could write a more direct solution that requires more code, but makes better use of machine resources:

(defun ascending-partitions (list)
  (let (partition output prev)
    (each ((item list))         ;; use (dolist (item list)  in Common Lisp
      (when (and prev (<= item prev))
        (when partition
          (push (nreverse partition) output)
          (set partition nil))) ;; use setf or setq in Common Lisp
      (push item partition)
      (set prev item))          ;; ditto
    (when partition
      (push (nreverse partition) output))
    (nreverse output)))

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...