替换嵌套引用列表中的元素会添加新元素吗? [英] Replace elements in nested quoted lists adds new elements?

查看:51
本文介绍了替换嵌套引用列表中的元素会添加新元素吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个嵌套列表,并且我试图无损地替换其所有元素(也在嵌套列表内).也就是说,根据我的输入列表

I have a nested list, and I am trying to non-destructively replace all its elements (inside the nested list as well). That is, given my input list

'(1 '(2 3 4) '(5 6 7) 8 9)

我正在努力实现

'(0 '(0 0 0) '(0 0 0) 0 0)

我尝试了以下

 (defun subs-list (list value)
  "Replaces all elements of a list of list with given value"
  (loop for elt in list
       collect (if (listp elt)
           (subs-list elt value) 
           value)))

但是当我尝试

(subs-list '(1 '(2 3 4) '(5 6 7) 8 9) 0)
(0 (0 (0 0 0)) (0 (0 0 0)) 0 0)

是我得到的输出. 我在做什么错了?

is the output I get. What am I doing wrong?

推荐答案

马克的答案

Mark's answer and wdebeaum's answer explain why you're getting the results that you're getting; the nested quotes mean you've actually got a list like (1 (quote (2 3 4)) (quote (5 6 7)) 8 9), and you're replacing the symbol quote with 0, and that's why you get (0 (0 (0 0 0)) (0 (0 0 0)) 0 0). You probably want just '(1 (2 3 4) (5 6 7) 8 9) with no nested quotes.

值得指出的是,Common Lisp已经提供了用于无损替换cons树的功能,尽管:替代,和替代-否.也有破坏性版本: nsubst nsubst-if

It's worth pointing out that Common Lisp already provides a functions for non-destructively substituting in cons-trees, though: subst, subst-if, and subst-if-not. There are destructive versions, too: nsubst, nsubst-if, and nsubst-if-not. In particular, for this case you can just replace everything that's not a list with 0, either by using the complement function with listp and subst-if, or using listp and subst-if-not:

;; With `extra' elements because of the quotes:

(subst-if-not 0 #'listp '(1 '(2 3 4) '(5 6 7) 8 9))
;=> (0 (0 (0 0 0)) (0 (0 0 0)) 0 0) 

(subst-if 0 (complement #'listp) '(1 '(2 3 4) '(5 6 7) 8 9))
;=> (0 (0 (0 0 0)) (0 (0 0 0)) 0 0) 

;; With no `extra' elements:

(subst-if-not 0 #'listp '(1 (2 3 4) (5 6 7) 8 9))
;=> (0 (0 0 0) (0 0 0) 0 0)

(subst-if 0 (complement #'listp) '(1 (2 3 4) (5 6 7) 8 9))
;=> (0 (0 0 0) (0 0 0) 0 0)

如果您想采用 wdebeaum的答案中建议的混合方式,而不必替换引号,则可以可以做到:

If you wanted to take the hybrid approach suggested in wdebeaum's answer where you don't replace quotes, you can do that do:

(subst-if 0 (lambda (x)
              (not (or (listp x)
                       (eq 'quote x))))
          '(1 '(2 3 4) '(5 6 7) 8 9))
;=> (0 '(0 0 0) '(0 0 0) 0 0)

(subst-if-not 0 (lambda (x)
                  (or (listp x)
                      (eq 'quote x)))
          '(1 '(2 3 4) '(5 6 7) 8 9))
;=> (0 '(0 0 0) '(0 0 0) 0 0)

这篇关于替换嵌套引用列表中的元素会添加新元素吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆