我创造了一个很好的小例程:
(defun unzip (seq)
"Takes an even-length list and breaks it apart by evens/odd index"
(let ((oddresult '())
(evenresult '()))
(loop for n from 0 to (- (length seq) 1) do
(if (oddp n)
(push (nth n seq) oddresult)
(push (nth n seq) evenresult)))
(list (reverse oddresult) (reverse evenresult))))
Run Code Online (Sandbox Code Playgroud)
并使用它:
CL-USER> (unzip '(1 2 3 4 5 6))
((2 4 6) (1 3 5))
Run Code Online (Sandbox Code Playgroud)
但是,我敏锐地意识到我能用任何语言编写 botch C++,并希望对我unzip的Common Lisp风格进行一些分析.
Ram*_*ren 13
首先注意'()并且()是等价的,因为空列表是自我评估并且等于NIL,并且在任何情况下你都不需要LET中的那些,因为NIL`(let(variable)...)语法暗示,这就是为什么在给出起始值时,您需要在每个绑定周围使用括号.
LET对于这种情况,并非必须使用.更广泛地使用LOOP功能,此功能可写为:
(defun unzip (seq)
"Takes an even-length list and breaks it apart by evens/odd index"
(loop for n from 0
for element in seq
if (oddp n)
collect element into oddresult
else
collect element into evenresult
finally (return (list oddresult evenresult))))
Run Code Online (Sandbox Code Playgroud)
我个人更喜欢迭代迭代,使用它可以写成:
(defun unzip (seq)
"Takes an even-length list and breaks it apart by evens/odd index"
(iter (for element in seq)
(for n from 0)
(if (oddp n)
(collect element into oddresult)
(collect element into evenresult))
(finally (return (list oddresult evenresult)))))
Run Code Online (Sandbox Code Playgroud)
甚至:
(defun unzip (seq)
"Takes an even-length list and breaks it apart by evens/odd index"
(iter (generate element in seq)
(collect (next element) into evenresult)
(collect (next element) into oddresult)
(finally (return (list oddresult evenresult)))))
Run Code Online (Sandbox Code Playgroud)
编辑:附加说明:名称unzip通常表示略有不同的功能.参数名称应该是真的list,因为它seq会暗示该函数也需要向量.虽然可以使功能在通用序列上运行,但通常不推荐使用,因为列表和向量具有不同的性能特征.特别是,随机访问NTH是列表的线性时间,这意味着您几乎不应该使用它.即使时间成本微不足道,它通常也表明您应该使用不同的数据结构.
该函数(nth n list)需要遍历列表以访问第n个元素,即O(n)操作,并在实现中调用O(n)次,使整个过程为O(n ^ 2).您可以在O(n)中完成相同的操作:
(defun unzip (list)
(loop for (x y) on list by #'cddr
collect x into a
collect y into b
finally (return (list a b))))
for-each您应该使用orcar和迭代列表直到列表为空,而不是cdr循环遍历列表的元素。unzip因为它不是 的反义词zip。编辑:更具体地说,我希望zip获取一对列表并返回一对列表,因此unzip应该获取一对列表并返回一对列表。我希望它看起来像我发现的这个例子:
(defun unzip (list)
(let ((a '())
(b '()))
(for-each (lambda (i) (push (first i) a) (push (second i) b)) list)
(values (nreverse a) (nreverse b))))
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1008 次 |
| 最近记录: |