从字符序列创建字符串

发布于 2024-12-02 20:03:06 字数 400 浏览 0 评论 0原文

这段代码没有按我的预期工作。您能解释一下原因吗?

(defn make-str [s c]
    (let [my-str (ref s)]
    (dosync (alter my-str str c))))

(defn make-str-from-chars
    "make a string from a sequence of characters"
    ([chars] make-str-from-chars chars "")
    ([chars result]
        (if (== (count chars) 0) result
        (recur (drop 1 chars) (make-str result (take 1 chars))))))

谢谢你!

This code does not work as I expected. Could you please explain why?

(defn make-str [s c]
    (let [my-str (ref s)]
    (dosync (alter my-str str c))))

(defn make-str-from-chars
    "make a string from a sequence of characters"
    ([chars] make-str-from-chars chars "")
    ([chars result]
        (if (== (count chars) 0) result
        (recur (drop 1 chars) (make-str result (take 1 chars))))))

Thank you!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

撞了怀 2024-12-09 20:03:06

这是非常慢的&从字符序列创建字符串的方法不正确。主要问题是更改不会传播 - ref 创建对现有字符串的新引用,但在退出函数后,引用将被销毁。

正确的做法是:

(apply str seq)

例如,

 user=> (apply str [\1 \2 \3 \4])
 "1234"

如果你想让它更有效,那么你可以使用Java的StringBuilder来收集字符串中的所有数据。 (Java中的字符串也是不可变的)

This is very slow & incorrect way to create string from seq of characters. The main problem, that changes aren't propagated - ref creates new reference to existing string, but after it exits from function, reference is destroyed.

The correct way to do this is:

(apply str seq)

for example,

 user=> (apply str [\1 \2 \3 \4])
 "1234"

If you want to make it more effective, then you can use Java's StringBuilder to collect all data in string. (Strings in Java are also immutable)

千年*琉璃梦 2024-12-09 20:03:06

您将包含一个字符的序列传递给 make-str 函数,而不是字符本身。使用 first 而不是 take 应该会给您带来所需的效果。

也不需要使用参考文献。实际上,您对它们的使用是对它们的严重滥用。您已经在函数中使用了累加器,因此可以直接使用 str

(defn make-str-from-chars
  "make a string from a sequence of characters"
  ([chars] (make-str-from-chars chars ""))
  ([chars result]
    (if (zero? (count chars))
      result
      (recur (drop 1 chars) (str result (first chars))))))

当然,在这种情况下 count 并不是很好,因为它总是必须遍历整个序列才能算出其长度。因此,您不必要地多次遍历输入序列。人们通常使用seq来识别序列何时耗尽。我们还可以使用 next 而不是 drop 来节省创建不必要的序列对象的一些开销。请务必捕获 seq 的返回值,以避免稍后创建对象的开销。我们在 if-let 中执行此操作。

(defn make-str-from-chars
  "make a string from a sequence of characters"
  ([chars] (make-str-from-chars chars ""))
  ([chars result]
     (if-let [chars (seq chars)]
       (recur (next chars) (str result (first chars)))
       result)))

像这样的函数,在完全消耗其输入后仅返回累加器,迫切需要reduce

(defn make-str-from-chars
  "make a string from a sequence of characters"
  [chars]
  (reduce str "" chars))

这已经很好很短了,但在这种特殊情况下,我们可以通过使用 apply 做得更好。然后 str 可以充分利用底层 StringBuilder 的功能。

(defn make-str-from-chars
  "make a string from a sequence of characters"
  [chars]
  (apply str chars))

希望这有帮助。

You pass a sequence with one character in it to your make-str function, not the character itself. Using first instead of take should give you the desired effect.

Also there is no need to use references. In effect your use of them is a gross misuse of them. You already use an accumulator in your function, so you can use str directly.

(defn make-str-from-chars
  "make a string from a sequence of characters"
  ([chars] (make-str-from-chars chars ""))
  ([chars result]
    (if (zero? (count chars))
      result
      (recur (drop 1 chars) (str result (first chars))))))

Of course count is not very nice in this case, because it always has to walk the whole sequence to figure out its length. So you traverse the input sequence several times unnecessarily. One normally uses seq to identify when a sequence is exhausted. We can also use next instead of drop to save some overhead of creating unnecessary sequence objects. Be sure to capture the return value of seq to avoid overhead of object creations later on. We do this in the if-let.

(defn make-str-from-chars
  "make a string from a sequence of characters"
  ([chars] (make-str-from-chars chars ""))
  ([chars result]
     (if-let [chars (seq chars)]
       (recur (next chars) (str result (first chars)))
       result)))

Functions like this, which just return the accumulator upon fully consuming its input, cry for reduce.

(defn make-str-from-chars
  "make a string from a sequence of characters"
  [chars]
  (reduce str "" chars))

This is already nice and short, but in this particular case we can do even a little better by using apply. Then str can use the underlying StringBuilder to its full power.

(defn make-str-from-chars
  "make a string from a sequence of characters"
  [chars]
  (apply str chars))

Hope this helps.

甜柠檬 2024-12-09 20:03:06

您还可以使用 clojure.string/join,如下所示:

(require '[clojure.string :as str] )
(assert (= (vec "abcd")                [\a \b \c \d] ))
(assert (= (str/join  (vec "abcd"))    "abcd" ))

clojure.string/join 有另一种形式,它接受分隔符。请参阅:

http://clojuredocs.org/clojure_core/clojure.string/join

You can also use clojure.string/join, as follows:

(require '[clojure.string :as str] )
(assert (= (vec "abcd")                [\a \b \c \d] ))
(assert (= (str/join  (vec "abcd"))    "abcd" ))

There is an alternate form of clojure.string/join which accepts a separator. See:

http://clojuredocs.org/clojure_core/clojure.string/join

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文