在Clojure中有更好的方法吗?

3

我有一个函数用于读取文件并将其转换为由两个元素列表组成的列表:

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

我将使用 cond 来正确地进行文件分割(我的两种类型的文件,第一种是通过空格分隔元素,第二种是通过制表符)。

第一种类型的文件如下:

"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来完成它。

1个回答

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从字符串两端去除任何空白。)

谢谢!太好了!这里我误加了引号,文件中只有数字。 - Jon Cardoso-Silva

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接