将哈希映射的集合转换为csv文件

时间:2013-09-02 11:25:49

标签: clojure

我有以下哈希映射集合:

{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

非常感谢任何帮助。

5 个答案:

答案 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)

  1. 使用data.json将json转换为一系列clojure贴图。

  2. 使用地图解构转换为字符串序列:(map #(let [{a :a b :b c :c d :d} %] (str a "," b "," c "," d, "\n")) <your sequence of clojure maps>)

  3. 将字符串序列转储到文件

答案 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-datawrite-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)

希望对某人有用!