问题
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
回答1:
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)))
来源:https://stackoverflow.com/questions/56436039/how-to-order-a-list-in-sublists-in-lisp