假设我的文件行显示为apple,pie,100,1000
。从每一行我想有一个像["apple" "pie" 100 1000]
这样的向量,其中前两个是字符串,第二个是整数或长整数或其他。
解决方案可能是
(defn foo [line]
(let [[a b c d] (split line #",")]
[a b (Integer/parseInt c) (Integer/parseInt d)]))
做了我想做的事,但我不确定是否有更好(或更惯用)的方式来做这件事。
从这个问题What's the easiest way to parse numbers in clojure?,我发现了clojure.edn,所以我可以像这样使用read-line
(map read-string (clojure.string/split "apple,pie,12,134" #","))
;=> (:apple :pie 12 134)
但是这给了我符号而不是字符串。
此问题Convert a sequence of strings to integers (Clojure)也类似,只是这些行只包含数字而不包含数字和字符串。
注意:clojure-csv(https://github.com/davidsantiago/clojure-csv)和clojure.data.csv(https://github.com/clojure/data.csv)似乎没有自动执行此操作的功能。
答案 0 :(得分:3)
您可以使用data.csv来解析数据,使用Prismatic的schema将字段值强制转换为所需的类型:
;; [org.clojure/data.csv "0.1.2"]
;; [prismatic/schema "0.2.2"]
(require '[schema.core :as s]
'[schema.coerce :as coerce]
'[clojure.data.csv :as csv])
(def field-schemas [s/Str s/Str s/Int s/Int])
(def field-coercers
(mapv coerce/coercer
field-schemas
(repeat coerce/string-coercion-matcher)))
(defn coerce-fields [fields]
(mapv #(%1 %2) field-coercers fields))
最后:
(map coerce-fields (csv/read-csv "apple,pie,12,134"))
;= (["apple" "pie" 12 134])
答案 1 :(得分:0)
我认为那里有一个图书馆让这很容易。不记得它的名字,但它的工作原理如此
(let [structure [str str int int]]
(map #(% %2)
structure
(map read-string (clojure.string/split "apple,pie,12,134" #",")))
;=> ("apple" "pie" 12 134)
答案 2 :(得分:0)
不是很优雅,但是
(map numberise (clojure.string/split "apple,pie,12,134" #","))
; ("apple" "pie" 12 134)
,其中
(defn numberise [s]
(try (Integer/parseInt s)
(catch NumberFormatException nfe s)))