Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List 从LISP中的嵌套列表中获取元素_List_Nested_Lisp_Common Lisp - Fatal编程技术网

List 从LISP中的嵌套列表中获取元素

List 从LISP中的嵌套列表中获取元素,list,nested,lisp,common-lisp,List,Nested,Lisp,Common Lisp,我试图弄清楚如何在LISP中访问嵌套列表中的元素。例如: ((3(17)((5)))4) 如果我使用dolist,我会遇到括号。有什么方法可以直接从列表中获取元素吗?这实际上是一个非常微妙的问题!在某些方面,这相当于问:如何通过指定模式获得HTMLDOM的嵌套元素。(稍后将详细介绍这方面的内容) 如果您只想将非列表元素作为序列获取,例如 ((3 (1 7) (((5)))) 4) --> (nth 3 (3 1 7 5 4)) --> 5 您可以使用“作弊”方式:CL ale

我试图弄清楚如何在LISP中访问嵌套列表中的元素。例如:

((3(17)((5)))4)


如果我使用dolist,我会遇到括号。有什么方法可以直接从列表中获取元素吗?

这实际上是一个非常微妙的问题!在某些方面,这相当于问:如何通过指定模式获得HTMLDOM的嵌套元素。(稍后将详细介绍这方面的内容)

如果您只想将非列表元素作为序列获取,例如

((3 (1 7) (((5)))) 4) --> 
(nth 3 (3 1 7 5 4)) -->
5  
您可以使用“作弊”方式:CL alexandria库中的
flatten
函数。(via)

这给了我们受欢迎的

5
但是,alexandrian函数非常简单,我们可以查看源代码本身:

(defun flatten (list)
  (cond 
    ((null list)
     nil)
    ((consp (car list))
     (nconc (flatten (car list)) (flatten (cdr list))))
    ((null (cdr list))
     (cons (car list) nil))
    (t
     (cons (car list) (flatten (cdr list))))))
正如你所看到的,它是一个递归函数——在递归的每一个层次上,它都会问这样一个问题:我要展平的对象是什么?如果是空列表,则返回nil。我完了

否则,它必须是非空列表。如果列表的第一个元素也是一个列表,则将其展平,并展平函数参数列表的
cdr
,并连接结果

如果第一个元素不是列表,而第二个元素是
”()
,这意味着我们有一个包含一个元素的列表:返回它

最后一种情况是,列表中的第一个元素是一个原子,而列表的其余部分是一个至少包含一个元素的列表。在这种情况下,将第一个元素与对列表其余部分执行的
展平的结果连接起来

事实上,英语中的描述是如此冗长,这表明了递归的力量(以及我自己在描述它时缺乏流利性)

但实际上还有另一种解释你的问题的方式:如果我有一个列表,看起来像:
((n1(n2-n3)((n4)))n5)
我如何到达
n2
,即使
n2
本身就是一个列表?我们以前的递归算法不起作用——它依赖于n2不是一个知道何时停止的列表。但是,我们仍然可以使用递归和我们正在搜索的列表作为模式的基础:

;; For each element in our pattern list look for a corresponding
;; element in the target, recursing on lists and skipping atoms that
;; don't match.
(defun extract-from-list (pattern target to-find)
  (dotimes (i (length pattern))
    (let ((ith-pattern (nth i pattern)))
      (cond
        ((consp ith-pattern)
          (let ((results
             (extract-from-list (nth i pattern)
                   (nth i target)
                   to-find)))
             (when results
               (return results))))
         (t
          (if (eq to-find ith-pattern)
             (return (nth i target))))))))
请注意

(extract-from-list
 '((n1 (n2 n3) (((n4)))) n5)   ;; The pattern describing the list.
 '((3 (1 7) (((5)))) 4)        ;; The list itself.
 'n4)                          ;; which of the elements we want.
仍然返回旧的答案:

 5
但是,

返回

 ((5))

魔法!Lisp的一个方面使它非常强大。

展平嵌套列表。@RainerJoswig我该怎么做?访问嵌套列表中的元素到底意味着什么?通过某种索引进行随机访问?一个接一个地打印它们?ncoder:最好先学习一点Lisp,然后再编写一个Lisp函数。当你对此有问题时,你可以发布你的代码,一些例子,你尝试过的东西和你遇到的问题。如果你能付出一些努力,那就太好了。我们已经解决了这些问题,现在轮到你了。基本上,我希望能够得到原始列表中所有元素的新列表,但这次没有括号。所以对于列表:((3(17)((5)))4)我想要一个新的列表,即:(3(17)5 4)
(extract-from-list
 '((n1 (n2 n3) (n4)) n5)   ;; The pattern describing the list, note (n4) rather than (((n4))) 
 '((3 (1 7) (((5)))) 4)    ;; The list itself.
 'n4)                      ;; The element we want to pull from the list
 ((5))