2013-07-09 46 views
3

我有这个功能来读取文件并将其转换为两个元素的列表清单:在Clojure中有更好的方法吗?

(def f1 "/usr/example") 

(defn read-file [file] 
    (let [f 
     (with-open [rdr (clojure.java.io/reader file)] 
      (doall (map list (line-seq rdr))))] 
    (cond 
     (= file f1) (map #(map read-string (split (first %) #" ")) f) 
     :else (map #(map read-string (split (first %) #"\t")) f)))) 

我用condsplit正确的文件(我有两种类型的文件,第一个分离的元素空间和第二个,带有标签)。

第一种类型的文件将是这样的:

"1.3880896237218878E9 0.4758112837388654 
1.3889631620596328E9 0.491845185928218" 

,而第二个是:

'1.3880896237218878E9\t0.4758112837388654 
1.3889631620596328E9\t0.491845185928218" 

我得到我想要的结果,例如:

((1.3880896237218878E9 0.4758112837388654) (1.3889631620596328E9 0.491845185928218)) 

但我想知道是否有一个更清洁的方式来做到这一点,也许使用更少的map函数或不使用cond

回答

4

这将返回一个向量向量,在任意空白处分割各条线,并使用Double/parseDouble来读取单个双精度值。它不处理的是文件中的任何单引号或双引号字符;如果它们是实际输入的一部分,我想我只是用一个正则表达式对它进行预处理来摆脱它们(见下文)。

(require '[clojure.java.io :as io] '[clojure.string :as string]) 

(defn read-file [f] 
    (with-open [rdr (io/reader f)] 
    (mapv (fn [line] 
      (mapv #(Double/parseDouble %) (string/split line #"\s+"))) 
      (line-seq rdr)))) 

至于上述预处理,你可以使用#(string/replace % #"['\"]" "")删除所有单引号。如果它们出现在输入的开始和结尾,或者可能是单独的行,那将是适当的。 (如果引用了单个数字,那么您需要确保不会删除它们之间的所有分隔符 - 在这种情况下,最好用一个空格替换,然后使用string/trim从两端删除任何空格)

+0

谢谢!那太棒了!我在这里误添加的引号,文件中只有数字。 –