(emacs)lisp:搜索((嵌套)列表中的任何内容)

yPh*_*hil 5 lisp algorithm emacs elisp

我需要找到一个可以隐藏在深层嵌套列表中的特定值,而不是在同一个地方.甚至相同的深度; 这是列表的一种形式:

(setq my-list '(((partnum . 1) (type (TEXT . plain)) (body (charset UTF-8))
                 (disposition nil) (transfer-encoding QUOTED-PRINTABLE))
                ((partnum . 2) (type (TEXT . html)) (body (charset UTF-8))
                 (disposition nil) (transfer-encoding QUOTED-PRINTABLE)))) 
Run Code Online (Sandbox Code Playgroud)

现在我需要检索"charset"的值; 第一个,如果有的话.在这个配置中,它很容易:

(car (cdr (cadr (third (car my-list)))))
   => UTF-8
Run Code Online (Sandbox Code Playgroud)

但是,当我确切知道"身体"细胞的位置时.

我尝试像这样递归地使用mapcar:

(defun search-rec (list)
  (mapcar
     (lambda (x)
       (if (listp x)
           (search-rec x)
         (message "OY %s" x)))
     list))
Run Code Online (Sandbox Code Playgroud)

但每次,(wrong-type-argument listp 1)当递归到达第一个cons单元的第一个原子时,我都会得到错误.我猜我的问题确实是这样的:

我如何在列表中搜索?

编辑现在列表看起来像这样,"charset"仍然在(身体)(告诉你这是唯一不变的事情)并且它不再被发现:(

(setq my-list '(((partnum . 1)
                (1.1 (type (TEXT . plain)) (body (charset UTF-8))
                     (disposition nil) (transfer-encoding 7BIT))
                (1.2 (type (TEXT . html)) (body (charset UTF-8))
                     (disposition nil) (transfer-encoding 7BIT))
                (type . alternative) (body (boundary e89a8fb2067eba300404c63c5f7f))
                (disposition nil) (transfer-encoding nil))
               ((partnum . 1.1) (type (TEXT . plain)) (body (charset UTF-8))
                (disposition nil) (transfer-encoding 7BIT))
               ((partnum . 1.2) (type (TEXT . html)) (body (charset UTF-8))
                (disposition nil) (transfer-encoding 7BIT))
               ((partnum . 2) (type (IMAGE . x-xpixmap)) (body (name ladybug.xpm))
                (disposition nil) (transfer-encoding BASE64))))
Run Code Online (Sandbox Code Playgroud)

编辑这里是一些更多的IRL示例:

    (setq my-list haystack-list)
    (setq my-needle (tree-assoc 'charset my-list))
    (message "
-------------\n
- my-list: %s\n
- my-needle: %s\n
-------------\n" my-list my-needle)
Run Code Online (Sandbox Code Playgroud)

生产:


  • 我的清单:((TEXT plain(charset UTF-8)nil nil 7BIT 260 18 nil nil nil)(TEXT html(charset UTF-8)nil nil nil nil nil nil nil nil nil nil nil nil)alternative(boundary e89a8fb1f8061a6be404c70a24a0)nil nil )

  • 我的针:没有


另一方面:

(tree-assoc 'charset '((TEXT plain (charset UTF-8) nil nil 7BIT 260 18 nil nil nil)
(TEXT html (charset UTF-8) nil nil QUOTED-PRINTABLE 738 17 nil nil nil) 
alternative (boundary e89a8fb1f8061a6be404c70a24a0) nil nil))
  =>(charset UTF-8)
Run Code Online (Sandbox Code Playgroud)

所以,我真的不知道这里发生了什么:人们可能会争辩说"干草堆是什么,它来自哪里?" 但这有关系吗?我正在研究这个干草堆列表的副本(我的列表),那么是什么给出了不同的结果呢?列表的引用?伙计们,我真的输了

注意(这种行为(在直接评估中工作,但不在defun/let生产情况下)与所有解决方案一起发生)

编辑:我最终提取了找到的第一个列表,然后从该列表中提取(不搜索)元素.我证明更快; 当然,这就是你可以说"我的元素总是在第一个列表中找到了";感谢所有人,我通过这一切学到了很多东西.

hua*_*uan 7

看起来你想要关联列表的树模拟.通过遵循assoc函数的约定,该函数检索包含给定键作为其头部的列表元素,这里是一个在树上工作的assoc版本:

(defun tree-assoc (key tree)
  (when (consp tree)
    (destructuring-bind (x . y)  tree
      (if (eql x key) tree
        (or (tree-assoc key x) (tree-assoc key y))))))
Run Code Online (Sandbox Code Playgroud)

例:

(let ((my-list '(((partnum . 1)
                  (1.1 (type (TEXT . plain)) (body (charset UTF-8))
                   (disposition nil) (transfer-encoding 7BIT))
                  (1.2 (type (TEXT . html)) (body (charset UTF-8))
                   (disposition nil) (transfer-encoding 7BIT))
                  (type . alternative) (body (boundary e89a8fb2067eba300404c63c5f7f))
                  (disposition nil) (transfer-encoding nil))
                 ((partnum . 1.1) (type (TEXT . plain)) (body (charset UTF-8))
                  (disposition nil) (transfer-encoding 7BIT))
                 ((partnum . 1.2) (type (TEXT . html)) (body (charset UTF-8))
                  (disposition nil) (transfer-encoding 7BIT))
                 ((partnum . 2) (type (IMAGE . x-xpixmap)) (body (name ladybug.xpm))
                  (disposition nil) (transfer-encoding BASE64)))))
  (tree-assoc 'charset my-list))

=> (charset UTF-8)
Run Code Online (Sandbox Code Playgroud)