Clojure,用集合

时间:2015-09-16 15:06:42

标签: clojure

首先,我不确定如何轻易说出标题。

我遇到的问题是提供一个字符串insert value here ?我希望能够将?替换为我选择的值,我可以使用clojure.string/replace执行此操作。

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

these are the specified values: ?, ?, ?, ?

我想将?的值替换为集合中的值,如下所示:

[2 389 90 13]

所以在这个例子中,字符串现在是:

these are the specified values: 2, 389, 90, 13

所以? x映射到collection x(例如? 0映射到collection 0

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

我尝试了以下操作:

(mapv #(clojure.string/replace-first statement "?" %) [1 2 3 4])

但是这不能产生预期的结果,产生大小为4的vector,其中只有第一个?被值替换。

由于无法修改clojure中的变量,我迷失了方向,并且我不希望有一个全局字符串被重新定义并传递给函数n次。

3 个答案:

答案 0 :(得分:6)

虽然我同意DaoWen's answer可能是最实用的,但你的问题的结尾似乎值得讨论一下以及学习功能方法的问题。你实际上是在寻找一种方法

  1. 获取初始字符串和第一个值,并使用replace-first从中创建另一个字符串。
  2. 从序列中获取结果和下一个值,并使用replace-first
  3. 重复2,直到您完成整个序列。
  4. 这实际上是数学和函数式编程中的经典模式,称为"左折"或者"减少"超过价值序列。函数式语言通常将其构建为标准库,作为更高阶函数。在Clojure中,它被称为reduce。使用它实现您的尝试策略看起来像

    (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"
    

    请注意,与您的类似函数文字不同,这需要两个参数,以便在我们进行缩减时statement可以反弹。
    如果您想查看reduce期间发生的情况,可以将其与reductions交换。你来了

    ("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
    

答案 1 :(得分:4)

您的问题可能还有其他一些注意事项 - 但正如所写的那样,您似乎应该只使用string format function

(apply format
       "these are the specified values: %s, %s, %s, %s"
       [2 389 90 13])
; => "these are the specified values: 2, 389, 90, 13"

答案 2 :(得分:1)

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)