将csv读入clojure中的列表

时间:2012-11-30 08:41:07

标签: clojure

我知道有很多相关的问题,我已经阅读了它们,但仍然没有对如何读取 - 处理 - 写入有一些基本的了解。以下面的函数为例,它使用clojure-csv库来解析一行

(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或更确切地说是记录列表。

3 个答案:

答案 0 :(得分:8)

“doseq”通常用于具有副作用的操作。在您创建记录集合的情况下,您可以使用“map”:

(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。

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

答案 1 :(得分: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“报告”,如财产评估,并将要上传的数据格式化为另一个金融系统的数据库,如计费。

我经常会zipmap每个.csv行,所以我可以按列名提取数据(读取列名),甚至可以创建一系列zipmap'ped .csv行。

答案 2 :(得分:0)

只需添加一个好的答案,这是一个完整的示例

首先,将clojure-csv添加到您的依赖项中

(ns scripts.csvreader
  (:require [clojure-csv.core :as csv]
            [clojure.java.io :as io]))

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

用法 (take-csv "/path/youfile.csv")