我正在编写一段需要在具有数据的文本文件中读取的代码。文本文件的格式为:
name 1 4
name 2 4 5
name 3 1 9
我正在尝试以[:name Sarah :weight 1 cost :4]
形式创建地图矢量。
当我尝试使用line-seq reader读取文件时,它会将每行读作项目,因此分区不正确。见下面的repl:
(let [file-text (line-seq (reader "C://Drugs/myproject/src/myproject/data.txt"))
new-test-items (vec (map #(apply struct item %) (partition 3 file-text)))]
(println file-text)
(println new-test-items))
(sarah 1 1 jason 4 5 nila 3 2 jonas 5 6 judy 8 15 denny 9 14 lis 2 2 )
[{:name sarah 1 1, :weight jason 4 5, :value nila 3 2 } {:name jonas 5 6, :weight judy 8 15, :value denny 9 14}]
然后我尝试只占用1个分区,但结构仍然不对。
=> (let [file-text (line-seq (reader "C://Drugs/myproject/src/myproject/data.txt"))
new-test-items (vec (map #(apply struct item %) (partition 1 file-text)))]
(println file-text)
(println new-test-items))
(sarah 1 1 jason 4 5 nila 3 2 jonas 5 6 judy 8 15 denny 9 14 lis 2 2 )
[{:name sarah 1 1, :weight nil, :value nil} {:name jason 4 5, :weight nil, :value nil} {:name nila 3 2 , :weight nil, :value nil} {:name jonas 5 6, :weight nil, :value nil} {:name judy 8 15, :weight nil, :value nil} {:name denny 9 14, :weight nil, :value nil} {:name lis 2 2, :weight nil, :value nil} {:name , :weight nil, :value nil}]
nil
接下来我试图啜饮文件,但情况更糟:
=> (let [slurp-input (slurp "C://Drugs/myproject/src/myproject/data.txt")
part-items (partition 3 slurp-input)
mapping (vec (map #(apply struct item %) part-items))]
(println slurp-input)
(println part-items)
(println mapping))
sarah 1 1
jason 4 5
nila 3 2
jonas 5 6
judy 8 15
denny 9 14
lis 2 2
((s a r) (a h ) (1 1) (
请帮忙!这在Java中似乎很容易做到,但在Clojure中杀了我。
答案 0 :(得分:7)
将其拆分为一系列行:
(line-seq (reader "/tmp/data"))
将每个人分成一系列单词
(map #(split % #" ") data)
创建一个函数,该函数采用一个数据的向量并将其转换为具有正确键的映射
(fn [[name weight cost]]
(hash-map :name name
:weight (Integer/parseInt weight)
:cost (Integer/parseInt cost)))
然后将它们重新组合在一起
(map (fn [[name weight cost]]
(hash-map :name name
:weight (Integer/parseInt weight)
:cost (Integer/parseInt cost)))
(map #(split % #" ") (line-seq (reader "/tmp/data"))))
({:weight 1, :name "name", :cost 4}
{:weight 2, :name "name", :cost 4}
{:weight 3, :name "name", :cost 1})
您还可以使用zip-map
答案 1 :(得分:3)
你试图在一个地方做所有事情而不测试中间结果。相反,Clojure建议将任务分解为多个子任务 - 这使得代码更加灵活和可测试。这是你的任务的代码(我假设文件中的记录描述了人):
(defn read-lines [filename]
(with-open [rdr (clojure.java.io/reader filename)]
(doall (line-seq rdr))))
(defn make-person [s]
(reduce conj (map hash-map [:name :weight :value] (.split s " "))))
(map make-person (read-lines "/path/to/file"))