Clojure,使用集合中不同的值替换字符的每个实例

Clojure,使用集合中不同的值替换字符的每个实例,clojure,Clojure,首先,我不知道如何轻松地说出标题 我遇到的问题是在此处提供一个字符串插入值?我希望能够用我选择的值交换?,我可以使用clojure.string/replace执行此操作 现在,我需要的用例稍微复杂一点,给定如下字符串: 这些是指定的值:?,?,?,? 我想用集合中的值替换?的值,该集合可能如下所示: [23899013] 因此,在本例中,字符串现在应为: 这些是指定的值:2389、90、13 那么?x映射到集合x(例如?0映射到集合0) ?的数量并不总是4或特定的n,但是集合的长度将始终与?的

首先,我不知道如何轻松地说出标题

我遇到的问题是在此处提供一个字符串
插入值?
我希望能够用我选择的值交换
,我可以使用
clojure.string/replace
执行此操作

现在,我需要的用例稍微复杂一点,给定如下字符串:

这些是指定的值:?,?,?,?

我想用集合中的值替换
的值,该集合可能如下所示:

[23899013]

因此,在本例中,字符串现在应为:

这些是指定的值:2389、90、13

那么
?x
映射到
集合x
(例如
?0
映射到
集合0

的数量并不总是4或特定的n,但是集合的长度将始终与
的数量相同

我试着做了以下几点:

(mapv #(clojure.string/replace-first statement "?" %) [1 2 3 4])
但这不会在生成大小为4的
向量时产生所需的结果,其中只有第一个
被值替换


由于无法修改clojure中的变量,我迷路了,我不想让全局字符串被重新定义并传递给函数
n次。

您的问题可能没有涉及到其他注意事项,但如前所述,您似乎应该使用:


DaoWen已经给出了字符串的实用答案,但您必须首先将“?”替换为“%s”

但假设这不是一根绳子。Clojure有一个很棒的集合库,这通常意味着您可以避免递归或约简,但我想不出一种方法来做到这一点,而不会变得非常低效和混乱。因此,这里有一个
reduce
解决方案,适用于非字符串,并带有大量注释

(let [original "these are the specified values: ?, ?, ?, ?"
      replacements [2 389 90 13]
      starting-accumulator [[] replacements] ; Start with an empty vector and all of the replacements.
      reducing-fn (fn [[acc [r & rs :as all-r]] o] ; Apply destructuring liberally
                    (if (= o \?) ; If original character is "?".
                      [(conj acc r) rs] ; Then add the replacement character and return the rest of the remaining replacements.
                      [(conj acc o) all-r])) ; Else add the original character and return all the remaining replacements.
      reduced (reduce reducing-fn starting-accumulator original) ; Run the reduce.
      result (first reduced) ; Get the resulting seq (discard the second item: the remaining empty seq of replacements).
      string-joined (apply str result)] ; The string was turned into a seq of chars by `reduce`. Turn it back into a string.
  string-joined)
虽然我同意这可能是最实际的,但你问题的结尾似乎值得讨论一下,同时也是学习函数方法的问题。你基本上是在寻找一种

  • 获取初始字符串和第一个值,并使用
    replace first
    从中生成另一个字符串
  • 从序列中获取该结果和下一个值,并对其使用
    replace first
  • 重复2次,直到完成整个序列 这实际上是数学和函数编程中的一个经典模式,称为值序列的“左折”或“缩减”。函数式语言通常将其作为高阶函数构建到标准库中。在Clojure,它被称为。用它来实现您尝试的策略

    (reduce #(clojure.string/replace-first %1 "?" %2) 
        "these are the specified values: ?, ?, ?, ?" 
         [2 389 90 13])
    ; => "these are the specified values: 2, 389, 90, 13"
    
    请注意,与类似的函数literal不同,这需要两个参数,因此当我们进行缩减时,
    语句可以反弹。
    如果您想查看使用
    reduce
    时会发生什么,可以使用
    reduces
    将其替换掉。给你

    ("these are the specified values: ?, ?, ?, ?" ;After 0 applications of our replace-first fn
     "these are the specified values: 2, ?, ?, ?" ;;Intermediate value after 1 application
     "these are the specified values: 2, 389, ?, ?" ;;after 2...
     "these are the specified values: 2, 389, 90, ?"
     "these are the specified values: 2, 389, 90, 13");;Final value returned by reduce
    

    我喜欢这个!使用
    replace first
    进行缩减是一个聪明的解决方案。
    ("these are the specified values: ?, ?, ?, ?" ;After 0 applications of our replace-first fn
     "these are the specified values: 2, ?, ?, ?" ;;Intermediate value after 1 application
     "these are the specified values: 2, 389, ?, ?" ;;after 2...
     "these are the specified values: 2, 389, 90, ?"
     "these are the specified values: 2, 389, 90, 13");;Final value returned by reduce