2012-11-30 7 views
5

私は多くの関連する質問があることを知っていますが、私はそれらを読んだことがありますが、まだ読み書き処理の基本的な理解を得ていません。私が取得したいどのようなライン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)])))) 

を解析するclojure-csvライブラリを利用した例えば次の関数を取ると、それを処理する(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の名前をtake-csvに変更するだけです。あなたは.CSVファイルを使用して実行できるすべてのもの、私が使用することをお勧めして

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

ニース。今はすべてが 'put-csv'に残されていますが、助けてくれますか? –

+0

これを追加しました。 – mobyte

+0

doallに注意してください: を使用して強制的にエフェクトを適用できますか? のseqを連続して歩き、頭を保持してそれを返します。したがって、 seq全体が一度にメモリに常駐します。 – micrub

2

Clojureは、CSVまたはclojure.data.csv。私は主に.csvファイルを読み込むためにclojure-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ファイルを読み込んだら、その内容で行うことは別の問題です。通常、私は資産評価などの1つの金融システムから.csv "レポート"を取り込み、課金のような別の金融システムのデータベースにアップロードするデータをフォーマットしています。

私は多くの場合、それぞれの.csv行のいずれかになりますので、列名でデータを抽出したり、zipmap「ped .csv rows」のシーケンスを作成することもできます。

+0

ありがとうございます。それでも、ファイル全体をメモリに読み込むというあなたのコメントを聞くのは面白いでしょう。これは[非常に大きなファイル](http://clojurewise.blogspot.com/2011/02/reading-csv-files.html)の問題かもしれません。 )。 –

+0

私が知る限り、それは怠惰な一連のマップです。 clojure-csvはレイジーシーケンスを返し、zipmapも同様です。それが私のやり方です。 – octopusgrabbus

関連する問題