【问题标题】:Scheme procedure to replace elements in a list替换列表中元素的方案过程
【发布时间】:2020-07-17 10:39:15
【问题描述】:

我正在尝试在方案中创建一个过程,用另一个元素替换列表中的某个元素

(define (replace var player list)
  (if (null? list)
      '()
     (if (list? (car list))
                (cons (replace var player (car list))          
                      (replace var player (cdr list))
          (if (equal? var (car list))
              (cons player (replace var player (cdr list)))
              (cons (car list) (replace var player (cdr list)))
          ))))

目前该过程不替换任何元素。 这是输入列表

'(q w (e r (t x)) y u i (o (x)) p x a s d)

我想将该列表中的“x”元素替换为“y”。

这是想要的输出

'(q w (e r (t y)) y u i (o (y)) p y a s d)

我们已经尝试过

(replace_by 'x 'y '(q w (e r (t x)) y u i (o (x)) p x a s d) 

但它似乎不起作用

【问题讨论】:

  • 这段代码似乎可以正常工作,至少对于给定的列表来说是这样(尽管我确信它的结构可以更好)。缺少 ')' 来关闭第一个 cons 即 (replace var player (cdr list)) ) 并且没有理由将 replace_by 放在代码中,只有 replace需要
  • 超级复制警报
  • @ghosh -- 这对我来说看起来不是一个好的欺骗候选人。在这里,OP 有一个小问题导致代码无法正常工作。我在回答中解决了这个问题:放错位置的括号没有导致输出。但更糟糕的是,你提出的骗局:唯一答案中描述的算法不会下降到嵌套列表,这里的 OP 代码会这样做。
  • @exnihilo np 你可能是对的,但这个问题是如此常见/基本/琐碎,99.9% 的人已经在某个地方得到了回答,很可能甚至在网站上......
  • @ghosh - 这基本上是一个调试问题,找到另一个缺少括号的问题应该很容易,但根本没有用。但是 OP 代码有一个更深层次的通用性问题,因为它能够在括号固定时替换嵌套列表中的 atom 元素,但它不能替换 list 元素(甚至没有空列表元素'())。您也许可以为这个更罕见的问题找到一个骗子,但 IAC 建议的骗子绝对没有解决这里的任何问题。

标签: list scheme


【解决方案1】:

发布的代码末尾缺少一个括号,并且括号放错了位置。第一个cons 表达式需要用括号括起来:

(define (replace var player list)
  (if (null? list)
      '()
     (if (list? (car list))
         (cons (replace var player (car list))          
               (replace var player (cdr list)))
         (if (equal? var (car list))
             (cons player (replace var player (cdr list)))
             (cons (car list) (replace var player (cdr list)))))))

在这些更正之后,OP 代码适用于要替换的项目是非列表的嵌套列表。但是,当要替换的项目是列表时,它会失败。这是因为输入中遇到的列表元素永远不会与var 进行相等性检查。另请注意,在 Scheme 函数中使用 list 作为形式参数是个坏主意;这会影响内置的 list 函数。

这是一个将替换输入列表中的原子和列表的实现。在检查输入是否为原子之前,该函数会检查与old 是否相等。如果old 值不是equal? 到当前head 值,则该函数检查当前head 值是否是原子。如果是,那么那个原子(不是equal?old)被限制在tail 上调用replace 的结果上;请注意,空列表被视为原子('() 既是列表 又是 原子)并且在此阶段已经处理。否则,当前head 是一个非空列表,并且该函数下降到headtail

这里atom? 用于区分非空列表和原子,'() 被视为原子。一些方案包含atom? 的定义,但它不在 R5RS 或 R6RS 标准方案中。如果需要,您可以自己定义:

(define (atom? x)
  (not (pair? x)))

或者您可以在下面的代码中使用(not (pair? head)) 代替(atom? head),它使用atom?,因为名称似乎更具描述性。 let 表达式用于减少对carcdr 的调用次数,并阐明对replace 的递归调用的意图:

(define (replace old new xs)
  (if (null? xs)
      xs
      (let ((head (car xs))
            (tail (cdr xs)))
        (cond ((equal? head old)
               (cons new (replace old new tail)))
              ((atom? head)
               (cons head (replace old new tail)))
              (else
               (cons (replace old new head)
                     (replace old new tail)))))))

以下是一些交互示例:

> (replace 'a 'x '(1 2 a 3 4 a))
(1 2 x 3 4 x)

> (replace 'a 'x '(1 2 a (3 4 a (5 a (a (a)) 6 a) ()) a))
(1 2 x (3 4 x (5 x (x (x)) 6 x) ()) x)

> (replace '() 'x '(1 2 a (3 4 a (5 a (a (a)) 6 a) ()) a))
(1 2 a (3 4 a (5 a (a (a)) 6 a) x) a)

> (replace '(5 a (a (a)) 6 a) 'x '(1 2 a (3 4 a (5 a (a (a)) 6 a) ()) a))
(1 2 a (3 4 a x ()) a)

> (replace '(5 a (a (a)) 6 a) '(x (x x)) '(1 2 a (3 4 a (5 a (a (a)) 6 a) ()) a))
(1 2 a (3 4 a (x (x x)) ()) a)

【讨论】:

  • 对不起括号。谢谢你的回答
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-07-23
  • 2021-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多