【问题标题】:Scheme : Make operations on a list without changing its copy?方案:对列表进行操作而不更改其副本?
【发布时间】:2013-10-27 02:24:46
【问题描述】:

我有一个帮手来复制一个列表:

(define (list-copy list)
  (if (null? list)
      '()
      (cons (car list) (list-copy (cdr list)))))

那么,

(define (multList lst1 lst2)
  (define lstCopy2 (list-copy lst2))  
  (cond ((null? lst1) ())
        ((eq? (length lst1) (length lst2)) (cons (* (car lst1) (car lst2)) (multList (cdr lst1) (cdr lst2)))) 
        ((> (length lst1) (length lst2))
         (if (null? lst2) lstCopy2
         (cons (* (car lst1) (car lst2)) (multList (cdr lst1) (cdr lst2)))))
        (else '())))

我正在尝试将 lst2 复制到 lstCopy2 中,然后我希望 lstCopy2 在我处理 lst2 时保持不变,以便像最初一样调用 lst2(在 lstCopy2 的帮助下)。 在我的第三个条件(当长度 lst1 > 长度 lst2)当 lst2 =()时,我想继续这个过程,直到 lst1 是()。

感谢您的帮助

【问题讨论】:

  • 你有括号匹配的编辑器吗,如果有,打开它,如果没有。在单独的行中拖出括号很烦人。您应该依靠空格来显示代码结构,并使用括号匹配器来确保括号匹配空格。
  • 此外,如果您在列表中重复出现并且每次都在该列表上调用 length,那么代码可能会更加复杂,因为当您 cdr 向下时,列表的长度应该变得明显。它还将一个时间与输入列表的大小成正比的好过程转换为一个时间与输入列表大小的平方成正比的过程。与向量不同,求链表的长度是线性时间过程,而不是一个常数时间。

标签: list scheme


【解决方案1】:

据我所知,您的副本没有被使用。此外,没有任何过程会改变任何内容,因此对于列表的每个递归/元素,(equal? lst2 lstCopy2) 将始终为 #t

如果lst1lst2 短,或者您已到达列表末尾,您将收到错误消息,因为() 是非法表达式。也许你的意思是'()

这本可以写得更容易:

(require srfi/1)

(define (multList lst1 lst2)
  (define (aux lst1 lst2)
    (if (null? lst2)
        '()
        (cons (* (car lst1) 
                 (car lst2)) 
              (aux (cdr lst1) (cdr lst2)))))
  (aux (apply circular-list lst1) lst2))

(multList '(1 -1) '(1 2 3 4 5 6)) ; ==> (1 -2 3 -4 5 -6)

;; with srfi-1-version of map we can use it to make the code shorter
(define (multList lst1 lst2)
  (map * (apply circular-list lst1) lst2))

【讨论】:

  • 我现在只在 case length lst1 > length lst2 上工作,因为当 length lst1 = length lst2 时它工作得很好。
  • (multList '(9 2 4) '(1 2)) 你的函数在做什么 ===> (9 4) 我需要的是 ===> (9 4 9)跨度>
  • @Dovakin940 最后 9 个来自哪里?这也将使它不是真正的乘法,因为它不保留属性 ab = ba.
  • @Dovakin940 我不太关注。当列表之一是 '() 而你有 4 时,它是如何在上一次迭代中安装到 9 的?
  • 我错了,这就是我想要的:(multList '(9 2 4) '(1 2)) ==> (9 4 4)
【解决方案2】:

你正在以一种非常奇怪的方式处理这个问题。执行此操作的标准方法是定义内部函数。通常你内部函数然后调用它。

每次调用 multList 时,您都在制作 lst2 的副本,这不是我认为您想要的。

但我看不到您实际引用原始第二个列表的位置,所以我看不出您想要做什么的原因。

(define (multList oL1 oL2)
  (define (helper lst1 lst2)
     (cond ((null? lst1) '())   
           ((null? lst2) (helper lst1 oL2))
           (else
            (cons (* (car lst1) (car lst2)) 
                  (helper (cdr lst1) (cdr lst2))))))
  (helper oL1 oL2))

(multlist '(9 2 4) '(1 2))

;Value 14: (9 4 4)

(multlist '(1 2) '(9 2 4))

;Value 15: (9 4)

明白我所说的不是一个正确的乘法是什么意思吗? (multist a b) 并不总是与 (multlist b a) 相同。

【讨论】:

  • 我不希望进程在 lst2 到达 () 时停止,但它会在 lst2 开始时重新启动,直到 lst1 是 ()
  • 我正在尝试理解您的代码 :) 那么我必须进行哪些更改才能获得 : (multlist '(1 2) '(9 2 4)) ===> (9 4 4) 正如你之前所说的那样是一个适当的乘法 (multlist a b) = (multlist b a)
  • 如果您希望它与您所称的相同,您可能应该将 (helper oL1 0L2) 更改为 (let ((shorter ..) (longer ...)) (helper long更短))填充..作为适当的。并将辅助条件的第二种情况中的 oL2 引用更改为更短。
猜你喜欢
  • 2021-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-20
  • 1970-01-01
  • 1970-01-01
  • 2014-07-06
  • 2011-11-21
相关资源
最近更新 更多