我有以下哈希映射集合:
{a:"Completed" b:1 c:"Friday" d:4}
{a:"Started" b:1 c:"Monday" d:4}
{a:"In Progress" b:1 c:"Sunday" d:1}
{a:"Completed" b:3 c:"Tuesday" d:9}
如何在clojure中将其转换为CSV文件?
即
a,b,c,d
Completed,1,Friday,4
Started,1,Monday,4
In Progress,1,Sunday,1
Completed,3,Tuesday,9
非常感谢任何帮助。
答案 0 :(得分:13)
你没有明确表示你是从JSON开始的,但我们假设你是。
我会用cheshire
解析你的JSON字符串,在这种情况下,获得一个地图矢量
代表你的数据。我们假设你已经为了清酒而这样做了
简单,只需使用var
data
来避免
这个例子很混乱。
现在我们可以创建一个矢量矢量,然后使用 clojure.data.csv保存 结果到文件。
您可以使用lein try在REPL中尝试此操作。
如果您还没有lein try
,请按照设置说明操作,然后运行
lein try clojure.data.csv 0.1.2
。一旦你在这个依赖的REPL中:
(require '[clojure.data.csv :as csv] '[clojure.java.io :as io])
(def data
[{:a "Completed" :b 1 :c "Friday" :d 4}
{:a "Started" :b 1 :c "Monday" :d 4}
{:a "In Progress" :b 1 :c "Sunday" :d 1}
{:a "Completed" :b 3 :c "Tuesday" :d 9}])
(defn write-csv [path row-data]
(let [columns [:a :b :c :d]
headers (map name columns)
rows (mapv #(mapv % columns) row-data)]
(with-open [file (io/writer path)]
(csv/write-csv file (cons headers rows)))))
(write-csv "/tmp/results.csv" data)
现在您可以看到您的手工结果:
$ cat /tmp/results.csv
a,b,c,d
Completed,1,Friday,4
Started,1,Monday,4
In Progress,1,Sunday,1
Completed,3,Tuesday,9
答案 1 :(得分:1)
使用data.json将json转换为一系列clojure贴图。
使用地图解构转换为字符串序列:(map #(let [{a :a b :b c :c d :d} %] (str a "," b "," c "," d, "\n")) <your sequence of clojure maps>)
。
将字符串序列转储到文件
答案 2 :(得分:1)
(def data [{:a "Completed" :b 1 :c "Friday" :d 4}
{:a "Started" :b 1 :c "Monday" :d 4}
{:a "In Progress" :b 1 :c "Sunday" :d 1}
{:a "Completed" :b 3 :c "Tuesday" :d 9}])
(for [i (range (count data))]
(if (= i 0)
(do
(spit "data.csv" (str (clojure.string/join "," (map name (keys (data i)))) "\n") :append true)
(spit "data.csv" (str (clojure.string/join "," (vals (data i))) "\n") :append true))
(spit "data.csv" (str (clojure.string/join "," (vals (data i))) "\n") :append true)))
要查看结果:
$ cat data.csv
c,b,d,a
Friday,1,4,Completed
Monday,1,4,Started
Sunday,1,1,In Progress
Tuesday,3,9,Completed
这个答案更好,因为这种方法可以从数据中获取所有内容,而不需要对任何内容进行硬编码。此方法也不会使用除clojure.string/join
之外的任何额外库。
答案 3 :(得分:0)
使用clojure-csv库,轻松读写格式良好的csv。
答案 4 :(得分:0)
我阅读了所有答案,但我想要更通用和可重复使用的解决方案。
这是我想出的。您可以通过write-csv
单独或一起使用maps->csv-data
和write-csv-from-maps
。更重要的是,您不需要硬编码标题。只需传递你的地图矢量,你应该全部设置。
一个。 DIY方法
(require '[clojure.data.csv :as csv]
'[clojure.java.io :as io])
(defn write-csv
"Takes a file (path, name and extension) and
csv-data (vector of vectors with all values) and
writes csv file."
[file csv-data]
(with-open [writer (io/writer file)]
(csv/write-csv writer csv-data)))
(defn maps->csv-data
"Takes a collection of maps and returns csv-data
(vector of vectors with all values)."
[maps]
(let [columns (-> maps first keys)
headers (mapv name columns)
rows (mapv #(mapv % columns) maps)]
(into [headers] rows)))
(defn write-csv-from-maps
"Takes a file (path, name and extension) and a collection of maps
transforms data (vector of vectors with all values)
writes csv file."
[file maps]
(->> maps maps->csv-data (write-csv file)))
B中。语义CSV方法
或者,您可以使用semantic-csv
库。
maps->csv-data
将成为semantic-csv.core/vectorize
(require '[clojure.data.csv :as csv]
'[clojure.java.io :as io]
'[semantic-csv.core :as sc])
(defn write-csv
"Takes a file (path, name and extension) and
csv-data (vector of vectors with all values) and
writes csv file."
[file csv-data]
(with-open [writer (io/writer file)]
(csv/write-csv writer csv-data)))
(defn write-csv-from-maps
"Takes a file (path, name and extension) and a collection of maps
transforms data (vector of vectors with all values)
writes csv file."
[file maps]
(->> maps sc/vectorize (write-csv file)))
-
最后:
(def data
[{:a "Completed" :b 1 :c "Friday" :d 4}
{:a "Started" :b 1 :c "Monday" :d 4}
{:a "In Progress" :b 1 :c "Sunday" :d 1}
{:a "Completed" :b 3 :c "Tuesday" :d 9}])
(write-csv "/tmp/results.csv" data)
希望对某人有用!