我的代码中有以下行:
(spit path (prn-str job-data))
它确实很好地执行了一件事,列表中的每个项目都放在双引号之间......
( ":a" ":b" ":a" )
我想要的预期结果
( :a :b :a )
如何获得预期结果?
提前致谢!
答案 0 :(得分:2)
问题不在于这些项目是双引号本身,而是它们是字符串(而不是您期望的关键字)。
prn-str
,最终基于pr
,以“读者可以读取对象的方式”打印对象。这意味着字符串以双引号打印 - 否则读者将无法从符号中分辨字符串,或读取其中包含空格的字符串。有关Clojure读者的更多信息,请参阅here。
println
和print
旨在“为人类消费产生输出”,而不是将字符串放在双引号中。这就是为什么您看到prn-str
和println
之间输出的差异。
您可以使用class
验证这一点。如果您尝试(-> job-data first class)
,答案将为java.lang.String
或clojure.lang.Keyword
。
以下是一些示例,演示了与关键字和字符串一起使用时打印功能的不同行为:
(def str-job-data '(":a" ":b" ":c"))
(def key-job-data '(:a :b :c))
;; `println` prints both keywords and strings without quotes
(with-out-str (println str-job-data)) ;=> "(:a :b :c)\n"
(with-out-str (println key-job-data)) ;=> "(:a :b :c)\n"
;; `prn-str` prints the strings in quotes but the keywords without quotes
(prn-str str-job-data) ;=> "(\":a\" \":b\" \":c\")\n"
(prn-str key-job-data) ;=> "(:a :b :c)\n"
现在寻找可能的解决方案。如果您希望job-data
包含关键字,那么正确的修复最有可能修改job-data
。但是,如果不了解job-data
的生成方式,我无法提供更多指导。
如果出于某种原因你无法修改job-data
(例如,如果它是由你无法控制的代码生成的),并且你想在任何地方写出类似关键字的字符串,那么像@ maxthoursie的建议可能是你最好的选择。 (您可以假设只是切换到print
或println
,但这可能会对其他对象的打印方式产生不良影响。
(defn keyword-string->keyword [s]
(keyword (subs s 1)))
(spit path (prn-str (map keyword-string->keyword job-data)))
如果job-data
可能包含类似关键字的字符串以外的对象,则只能在适当的时候应用该函数。
(defn convert-job-data [obj]
(if (and (string? obj)
(= (.charAt obj 0) \:))
(keyword-string->keyword obj)
obj))
(spit path (prn-str (map convert-job-data job-data)))
当然,如果您正在撰写的文件仅供人类使用,并且所有与读者有关的业务都无关紧要,您可以轻松制作自己的println-str
:
(defn println-str [& more]
(with-out-str (apply println more)))
(spit path (println-str job-data))
答案 1 :(得分:0)
我猜工作数据并不是你所期望的那样。
user=> (prn-str '(:a :b :c))
"(:a :b :c)\n"
如果您的列表中包含类似于关键字的字符串,并且您希望将其转换为关键字,则可以使用类似
的内容 (map (comp keyword #(subs % 1)) '(":a" ":b" ":c"))
跳过每个元素的:然后将其转换为关键字。
user=> (prn-str (map (comp keyword #(subs % 1)) '(":a" ":b" ":c")))
"(:a :b :c)\n"