List 如何获取列表中某个位置的项的值?

List 如何获取列表中某个位置的项的值?,list,loops,lisp,common-lisp,List,Loops,Lisp,Common Lisp,我需要创建一个函数,用列表L中的Z替换所有出现的X和Y。我的问题是我的比较语句根据我的理解与位置本身进行比较 类似于在其他语言中循环时I值的工作方式?当我运行此代码时,它会替换位置3和位置7处的项目:(2 2 6 4 5 8 8 4)(2 2 7 6 4 5 7 5 8 4),而不是执行它应该执行的操作。所以我需要找出如何比较这个位置的值,而不是位置本身 如果我用print语句代替(replace)函数,它将打印26,所以我真的不明白这一点。我还尝试了(setf(nth Y Z)I)而不是具有相

我需要创建一个函数,用列表L中的Z替换所有出现的X和Y。我的问题是我的比较语句根据我的理解与位置本身进行比较

类似于在其他语言中循环时I值的工作方式?当我运行此代码时,它会替换位置3和位置7处的项目:
(2 2 6 4 5 8 8 4)
(2 2 7 6 4 5 7 5 8 4)
,而不是执行它应该执行的操作。所以我需要找出如何比较这个位置的值,而不是位置本身

如果我用print语句代替(replace)函数,它将打印
26
,所以我真的不明白这一点。我还尝试了
(setf(nth Y Z)I)
而不是具有相同结果的replace函数,这就是为什么我能够找出compare语句的问题所在。我也尝试过使用
eq
=
equal
来获得相同的结果

 (defun replace-z (X Y Z L)


 (loop for i in L
 do 
 (cond

 ((equal Y i) (replace L (list Z) :start1 i))

 ((= X i) (replace L (list Z) :start1 i)))) L) 
 (trace replace-z)
 (print (replace-z 2 6 7 '(2 2 2 6 4 5 8 4 5 8 4) ))
我的问题是,我的比较陈述是根据我的理解与立场本身进行比较

当您执行
(L中的i循环)
时,
i
依次获取
L中每个元素的值。您可以添加这样一个子句
(p从0循环到L中的i)
来声明一个计数器
p
,它表示列表中的当前位置

replace
中,
:start1
参数需要一个位置,因此您不想给它
i
,而是
p
,尽管这不是解决问题的最优雅的方法,当您在迭代过程中迭代
L
时:对于只需要一次遍历
L
的对象,这具有二次运行时间

顺便说一下,我不认为您应该在本练习中使用
replace
。其要点是能够做到这一点(
copy seq
是避免修改文字数据所必需的):

如果您想使用现有的标准函数,您可以使用;例如:

(defun replace-z (x y z l)
  (let ((to-replace (list x y)))
    (flet ((replacep (v) (member v to-replace)))
      (substitute-if z #'replacep L))))
如果我用print语句代替(replace)函数,它将打印26,所以我真的不明白这一点

由此产生的代码将是:

(defun replace-z (X Y Z L)
  (loop
     for i in L
     do (cond
          ((equal Y i) (print i))
          ((= X i) (print i))))
  L)
请注意,最后的
L
很难注意到(至少对我来说),通过使用
循环中的现有结构,可能可以使返回值更明确一些:

(defun replace-z (X Y Z L)
  (loop
     for i in L
     when (or (equal y i) (= x i))
     do (print i)
     finally (return L)))
当值
x
y
(请注意,
=
相等
的比较不同)时,您会打印
i
,这就是为什么您的输出是
26

我也尝试过使用eq、=、和equal,结果都是一样的

 (defun replace-z (X Y Z L)


 (loop for i in L
 do 
 (cond

 ((equal Y i) (replace L (list Z) :start1 i))

 ((= X i) (replace L (list Z) :start1 i)))) L) 
 (trace replace-z)
 (print (replace-z 2 6 7 '(2 2 2 6 4 5 8 4 5 8 4) ))
不要对数字和字符使用
eq
,因为允许实现对
(eq x x)
返回NIL,否则这些值是
eql
(例如,bignum整数)

我的问题是,我的比较陈述是根据我的理解与立场本身进行比较

当您执行
(L中的i循环)
时,
i
依次获取
L中每个元素的值。您可以添加这样一个子句
(p从0循环到L中的i)
来声明一个计数器
p
,它表示列表中的当前位置

replace
中,
:start1
参数需要一个位置,因此您不想给它
i
,而是
p
,尽管这不是解决问题的最优雅的方法,当您在迭代过程中迭代
L
时:对于只需要一次遍历
L
的对象,这具有二次运行时间

顺便说一下,我不认为您应该在本练习中使用
replace
。其要点是能够做到这一点(
copy seq
是避免修改文字数据所必需的):

如果您想使用现有的标准函数,您可以使用;例如:

(defun replace-z (x y z l)
  (let ((to-replace (list x y)))
    (flet ((replacep (v) (member v to-replace)))
      (substitute-if z #'replacep L))))
如果我用print语句代替(replace)函数,它将打印26,所以我真的不明白这一点

由此产生的代码将是:

(defun replace-z (X Y Z L)
  (loop
     for i in L
     do (cond
          ((equal Y i) (print i))
          ((= X i) (print i))))
  L)
请注意,最后的
L
很难注意到(至少对我来说),通过使用
循环中的现有结构,可能可以使返回值更明确一些:

(defun replace-z (X Y Z L)
  (loop
     for i in L
     when (or (equal y i) (= x i))
     do (print i)
     finally (return L)))
当值
x
y
(请注意,
=
相等
的比较不同)时,您会打印
i
,这就是为什么您的输出是
26

我也尝试过使用eq、=、和equal,结果都是一样的

 (defun replace-z (X Y Z L)


 (loop for i in L
 do 
 (cond

 ((equal Y i) (replace L (list Z) :start1 i))

 ((= X i) (replace L (list Z) :start1 i)))) L) 
 (trace replace-z)
 (print (replace-z 2 6 7 '(2 2 2 6 4 5 8 4 5 8 4) ))

不要将
eq
用于数字和字符,因为允许实现将
(eq x x)
返回NIL用于其他
eql
(例如,bignum整数)的值。

因为CL是一种工业强度语言,该语言已经提供了几个函数来执行类似的操作。然而,从学习Lisp的角度来看,最好考虑一下,如果不存在编写代码所需的算法,然后使用基本操作,而不是使用已经实现的函数之一来实际实现:这样做可以教你用Lisp编程,而查找和使用现有的工具会教你在手册中查找东西,这些是不同的技能

使用递归来解决这个问题 那么算法是什么呢

给定一个列表
l

  • 如果是空列表,我们就完成了
  • 如果它不是空的,则将其拆分为第一个元素和其余元素
  • 如果第一个元素为
    X
    Y
    ,则结果为
    (cons'Z…
    ),否则为
    (cons…
    ,其中
    (defun replace-things-with-thing (l things thing &key (test #'eql))
      (mapcar (lambda (e)
                (if (member e things :test test)
                    thing
                  e))
              l))
    
    (defun memp (elt list &key (test #'eql))
      (if (null list)
          nil
        (or (funcall test elt (first list))
            (memp elt (rest list) :test #'eql))))
    
    (defun memp (elt list &key (test #'eql))
      (labels ((memp-loop (tail)
                 (if (null tail)
                     nil
                   (or (funcall test elt (first tail))
                       (memp-loop (rest tail))))))
        (memp-loop list)))
    
    (define (mem? elt lst #:test (test? eqv?))
      (let mem-loop ([tail lst])
        (if (null? tail)
            #f
            (or (test? elt (first tail))
                (mem-loop (rest tail))))))
    
    (defun replace-things-with-thing (l things thing &key (test #'eql))
      ;; an absurdly purist, tail recursive version
      (labels ((memp (e tail)
                 ;; is E in TAIL compared using TEST.  In real life this
                 ;; would be MEMBER
                 (cond ((null tail)
                        nil)
                       ((funcall test e (first tail))
                        t)
                       (t (memp e (rest tail)))))
               (rev (tail accum)
                 ;; reverse TAIL. In real life this would be REVERSE
                 (if (null tail)
                     accum
                   (rev (rest tail) (cons (first tail) accum))))
               (replace-loop (tail accum)
                 ;; the implementation of the function
                 (if (null tail)
                     ;; we're done: the reverse of ACCUM is the answer
                     (rev accum '())
                   (let ((e (first tail)))
                     (replace-loop (rest tail)
                                   (cons (if (memp e things)
                                             thing
                                           e)
                                         accum))))))
        (replace-loop l '())))
    
    (substitute-if #\c (lambda (x) (member x '(#\a #\b))) "How about it?")
    --> "How ccout it?"
    
    (substitute-if 42 (lambda(x) (or (= x 0) (= x 1))) '(0 1 2 3 0 1))
    --> (42 42 2 3 42 42)
    
    (loop for x in '(0 1 2 3 0 1)
          if (or (= x 0) (= x 1))
            collect 42
          else
            collect x)
    --> (42 42 2 3 42 42)
    
    (loop with l = (list 0 1 2 3 0 1)
          for c on l       ; c means "cell"
          for x = (car c)
          if (or (= x 0) (= x 1)) do
            (rplaca c 42)
          finally (return l))
    --> (42 42 2 3 42 42)