0

想象一下我有一个类似的列表

(def nodes ["a", "b", "c"])

我想转换nodes成以下字符串:

a -> b -> c

我该怎么做?

(apply str (mapcat
             (fn [node]
               (str node " -> ")
               )
             nodes
             )
       )

结果是

"a -> b -> c -> "

我现在可以检查生成的字符串是否以结尾->,如果是,则删除最后一个->.

但这似乎不是很优雅。在 Clojure 中执行此操作的正确方法是什么?

更新1:

(transduce
  (fn [rf]
    (fn
      ([] "")
      ([result] result)
      ([result input] (str
                        result
                        "->"
                        input))
      )
    )
   cat
   ""
   nodes
  )

结果是

"->a->b->c"

4

3 回答 3

8
(def nodes ["a" "b" "c"])

(clojure.string/join " -> " nodes) ;; => "a -> b -> c"
于 2021-07-25T10:24:52.020 回答
3

clojure.string/join答案完全适合您的特定需求。

然而,为了更通用的解决方案,clojure.core/interpose从插入另一个序列的元素之间的固定项目创建一个序列。

(def nodes ["a" "b" "c"])
(interpose " -> " nodes)
;; => ("a" " -> " "b" " -> " "c")
(apply str (interpose " -> " nodes))
;; => "a -> b -> c"

值得注意的是,这需要大约 3 倍的时间,因此请确保您需要通用性!

(use 'criterium.core)
(quick-bench (clojure.string/join " -> " nodes))
;; => Execution time mean : 299.877733 ns
(quick-bench (apply str (interpose " -> " nodes)))
;; => Execution time mean : 950.765805 ns
于 2021-07-26T10:05:17.383 回答
1

除了,如果您愿意clojure.string/join,您还可以使用reduce自己制作join

(second (reduce #(vector nil (str (second %1)
                                  (if (= :begin (first %1))
                                    ""
                                    " -> ")
                                  %2))
                [:begin ""]
                ["a" "b" "c"]))

减少:https ://clojuredocs.org/clojure_core/clojure.core/reduce

于 2021-07-25T14:32:50.687 回答