6

我有以下哈希映射集合:

{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 文件?

IE

a,b,c,d
Completed,1,Friday,4
Started,1,Monday,4
In Progress,1,Sunday,1
Completed,3,Tuesday,9

对此的任何帮助将不胜感激。

4

5 回答 5

18

您没有明确表示您是从 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
于 2014-05-19T05:29:56.667 回答
3

我阅读了所有答案,但我想要更通用和可重用的解决方案。

这是我想出的。您可以通过单独或一起使用write-csvand 。更重要的是,您不需要对标头进行硬编码。只需传递您的地图矢量,您就应该准备就绪。maps->csv-datawrite-csv-from-maps

A. 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)

希望对某人有用!

于 2018-01-13T20:26:54.083 回答
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. 将字符串序列转储到文件中

于 2013-09-03T12:11:26.820 回答
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.

于 2016-02-02T11:53:01.943 回答
-2

使用clojure-csv库,轻松读写格式良好的 csv。

于 2017-07-02T10:26:58.650 回答