2013-07-09 78 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

謝謝!那太棒了!我在這裏誤添加的引號,文件中只有數字。 –