2012-11-30 69 views
5

我知道有很多相關的問題,我已經閱讀過它們,但仍未獲得關於如何讀取進程的基本知識。就拿下面的函數,它使用clojure-csv庫來解析線將csv讀入clojure的列表

(defn take-csv 
    "Takes file name and reads data." 
    [fname] 
    (with-open [file (reader fname)] 
    (doseq [line (line-seq file)] 
     (let [record (parse-csv line)])))) 

我想什麼來獲得的數據讀入到一些收藏爲一體(def data (take-csv "file.csv"))結果後來對其進行處理。所以基本上我的問題是我如何返回record或更確切地說是一個記錄列表。

回答

7

「doseq」通常用於有副作用的手術。在你的情況下創造的記錄集可以使用「地圖」:

(defn take-csv 
    "Takes file name and reads data." 
    [fname] 
    (with-open [file (reader fname)] 
    (doall (map (comp first csv/parse-csv) (line-seq file))))) 

更好地剖析了整個文件的人,以減少代碼:

(defn take-csv 
    "Takes file name and reads data." 
    [fname] 
    (with-open [file (reader fname)] 
    (csv/parse-csv (slurp file)))) 

您還可以使用clojure.data.csv代替clojure-csv.core。只有重命名parse-csv才能在之前的函數中使用-csv。

(defn put-csv [fname table] 
    (with-open [file (writer fname)] 
    (csv/write-csv file table))) 
+0

不錯。現在剩下的就是'put-csv',你能幫忙嗎? –

+0

我已經添加了這個。 – mobyte

+0

注意doall:doall可以用 強制任何效果。通過連續的下一個 seq,保留頭部並將其返回,從而導致整個seq在同一時間駐留在內存中。 – micrub

2

與所有的東西,你可以用的.csv文件做的,我建議使用Clojure的-CSV或clojure.data.csv。我主要使用clojure-csv來讀取.csv文件。

下面是我使用的大多數Clojure程序的實用程序庫中的一些代碼片段。

from util.core 

    (ns util.core 
     ^{:author "Charles M. Norton", 
     :doc "util is a Clojure utilities directory"} 

     (:require [clojure.string :as cstr]) 
     (:import java.util.Date) 
     (:import java.io.File) 
     (:use clojure-csv.core)) 

(defn open-file 
"Attempts to open a file and complains if the file is not present." 

[file-name] 
(let [file-data (try 
       (slurp file-name) 
       (catch Exception e (println (.getMessage e))))] 
    file-data)) 

(defn ret-csv-data 
"Returns a lazy sequence generated by parse-csv. 
Uses open-file which will return a nil, if 
there is an exception in opening fnam. 

parse-csv called on non-nil file, and that 
data is returned." 

[fnam] 
(let [csv-file (open-file fnam) 
     inter-csv-data (if-not (nil? csv-file) 
         (parse-csv csv-file) 
         nil) 

     csv-data 
     (vec (filter #(and pos? (count %) 
      (not (nil? (rest %)))) inter-csv-data))] 

    (if-not (empty? csv-data) 
     (pop csv-data) 
     nil))) 

(defn fetch-csv-data 
    "This function accepts a csv file name, and returns parsed csv data, 
    or returns nil if file is not present." 

    [csv-file] 
     (let [csv-data (ret-csv-data csv-file)] 
      csv-data)) 

一旦你閱讀了一個.csv文件,你對它的內容做了什麼是另一回事。通常,我正在從一個財務系統獲取.csv「報告」,例如財產評估,並將數據格式化爲上傳到另一財務系統的數據庫中,例如計費。

我通常會使用每個.csv行的zipmap,這樣我就可以按列名提取數據(讀入列名),甚至可以創建一個序列zipmap ped .csv行。

+0

謝謝。聽到你的評論將整個文件讀入內存也是很有趣的,這可能是[非常大的文件]的一個問題(http://clojurewise.blogspot.com/2011/02/reading-csv-files.html )。 –

+0

據我可以告訴它是一個懶惰的地圖序列。 clojure-csv返回一個懶惰的序列,而zipmap也是。我就是這麼做的。 – octopusgrabbus