Functional programming Racket中3个列表的函数编程

Functional programming Racket中3个列表的函数编程,functional-programming,scheme,racket,Functional Programming,Scheme,Racket,我可以管理以下代码,用另外两个列表替换列表中的项目。Orilist和newlist按顺序具有原始术语和新术语。使用orilist和newlist进行替换-如果orilist项存在于slist中,则slist将更改为具有来自newlist的相应新项: (define (list-replace-from-lists slist orilist newlist) (define replaced #f) (define outl '()) (for ((item slist))

我可以管理以下代码,用另外两个列表替换列表中的项目。Orilist和newlist按顺序具有原始术语和新术语。使用orilist和newlist进行替换-如果orilist项存在于slist中,则slist将更改为具有来自newlist的相应新项:

(define (list-replace-from-lists slist orilist newlist)
  (define replaced #f)
  (define outl '())
  (for ((item slist))
    (set! replaced #f)
    (for ((ori_ orilist) (i (in-naturals))  #:when (equal? item ori_))
      (set! outl (cons (list-ref newlist i) outl))
      (set! replaced #t))
    (when (not replaced)
      (set! outl (cons item outl))))
  (reverse outl))
将列表1 2 3 4 5 6中的2和5分别替换为12和15:

(list-replace-from-lists (list 1 2 3 4 5 6) (list 2 5) (list 12 15)) 
输出为:

'(1 12 3 4 15 6)
然而,上面的代码看起来并没有功能,并且有很多设置!声明。如何将其转换为功能代码?出于上述目的,我应该使用结构或其他数据类型吗


编辑:项目可能会在原始列表中重复出现,例如列表1 2 3 4 5 2 6

您仍然可以使用列表并保持一切功能正常:以下是我的解决方案:

(define (replace-all haystack needles new-needles)
  (define replace-alist (map cons needles new-needles))
  (define (replace-one item)
    (cond ((assoc item replace-alist) => cdr)
          (else item)))
  (map replace-one haystack))
守则解释:

首先,我们构建一个替换关联列表。这是对的列表,其中键对应于针,值对应于新针

然后我们定义一个replace one函数,它接受一个项,并查看它是否匹配列表中的任何键。如果是,我们返回相应的值;否则,我们将返回原始项目

最后,我们通过替换一来映射干草堆。是的,高阶函数


注意,这段代码是Om*n,其中m是草堆的大小,n是针的大小,与您的版本运行时相同。如果指针较大,您将希望使用哈希表而不是列表,这将把函数的运行时分摊到Om。

这是一个使用哈希来保持关联的函数解决方案。这使得该解决方案具有堆栈长度对数针长度,因为不可变哈希是用树实现的

(define (list-replace-all haystack needles new-values)
  ;; make a dictionary of elements to be replaced
  (define hash
    (foldl (λ (needle new-value hash)
             (hash-set hash needle new-value))
           #hash()
           needles
           new-values))
  ;; do the replace. If not in hash the actual key is default
  (map (λ (e) (hash-ref hash e e)) haystack))

(list-replace-all '(1 2 3 4 5 6) '(2 5) '(12 15))
; ==> (1 12 3 4 15 6)

如果项目稍后在haystack中再次出现,例如替换列表1 2 3 4 5 2 6列表2 5列表12 15,则您的解决方案不起作用。第二个2没有被替换。我发布了一个简单的示例,您的解决方案在这方面非常优雅。但不排除重复项目。完美。感谢您的解答以及清晰的解释。如果为了清晰起见,您可以将哈希表版本放在这里,这对所有读者都是非常好的。您能在这里解释一下=>的用法吗。这似乎是一个不常用的符号。@rnso Sylvester已经发布了一个哈希版本,所以我不想麻烦这么做了。.-至于=>,它是存储测试值的cond语法,如果是truthy,则将其传递给给定函数。在这种情况下,它相当于:如果值cdr value。。。在哪里。。。表示失败情况。首选使用for/hash作为此for/hash针在列表中针在列表中的新值新值针新值。否则,答案很好+我很高兴我的问题给出了有教育意义的答案。我不知道为什么这个问题被否决了。@ChrisJester Young是的,它看起来更清楚。为什么在列表中使用?两者都已经是一个列表,每个元素都将被触及@mso可能是因为它有效。“这更多的是一个问题,”西尔维斯特说,“这是一个微观优化。在不指定生成器的情况下,系统必须在运行时查看对象的类型以决定要使用的生成器。。列表mylist中项目的vs。在列表中,第二个版本要快得多。类似地,对于范围n中的i,速度比对于范围n中的i或i快得多。