使用LISP从列表'(3 2 1)'生成子列表'(((3)2)1)'的技术求助
Got it, let's break down how to turn '(3 2 1) into '(((3)2)1) in Lisp. First, let's spot the pattern here: we're building a nested structure where each step wraps the result of processing the previous elements in a list, then pairs it with the next element in the original list.
Recursive Approach (Intuitive)
The recursive method is straightforward once you see the pattern:
- If we have a single element (like
'(3)), we just return it wrapped in a list ('(3)) to start the nesting. - For longer lists, we recursively process all elements except the last one, then wrap that result in a list alongside the last element.
Here's the code:
(defun nest-left (lst) (cond ((null lst) nil) ; Handle empty list edge case ((null (cdr lst)) (list (car lst))) ; Single element: wrap in list (t (list (nest-left (butlast lst)) (car (last lst)))))) ; Recurse and combine
Testing it out:
(nest-left '(3)) ; Returns (3) (nest-left '(3 2)) ; Returns ((3) 2) (nest-left '(3 2 1)) ; Returns (((3) 2) 1)
Iterative Approach (More Efficient)
The recursive version works great for short lists, but it uses butlast and last which traverse the list each time—this can get slow for longer lists. An iterative approach avoids that by building the result step-by-step from left to right:
(defun nest-left-iter (lst) (if (null lst) nil (let ((result (list (car lst)))) ; Start with first element wrapped (dolist (elem (cdr lst) result) ; Iterate over remaining elements (setf result (list result elem)))))) ; Update result by wrapping with next element
This works by starting with '(3), then turning it into '((3)2) when processing 2, then into '(((3)2)1) when processing 1. Test it with:
(nest-left-iter '(3 2 1)) ; Returns (((3) 2) 1)
Either approach will get you the exact nested structure you need. The recursive one is easier to read and reason about for small cases, while the iterative one is better for performance with larger lists.
内容的提问来源于stack exchange,提问作者Dimamid

