[英]How to read contents from a file and store it in a hash-map in clojure?
I got a small problem in clojure.我在 clojure 中遇到了一个小问题。 I am new to this programming environment and need a little help.
我是这个编程环境的新手,需要一点帮助。 I have got a text file in this format:
我有一个这种格式的文本文件:
1|John Smith|123 Here Street|456-4567
2|Sue Jones|43 Rose Court Street|345-7867
3|Fan Yuhong|165 Happy Lane|345-4533
I want to parse each line in file and want to store data in hashmap in this way:我想解析文件中的每一行,并希望以这种方式将数据存储在 hashmap 中:
{ 1 : [John Smith, 123 here street, 456-4567], 2 : ... }
Here is my code till now but I have not got any success.到目前为止,这是我的代码,但我没有取得任何成功。
(defn readcustfile[]
(def cust-file (clojure.string/split-lines (slurp "cust.txt")))
(doseq [line cust-file]
(def cust-id (nth (clojure.string/split line #"\|") 0))
(def cust-name (str (nth (clojure.string/split line #"\|") 1)))
(def cust-add (str (nth (clojure.string/split line #"\|") 2)))
(def cust-phone (str (nth (clojure.string/split line #"\|") 3)))
(def cust-data (str cust-name "," cust-add "," cust-phone))
(def cust (map (fn [[id name add phone]]
(list (Integer/parseInt cust-id)
(hash-map :name cust-name
:add cust-add
:phone cust-phone))
)
)
(readcustfile)
what i would propose, is to read file line by line transducing it into resulting map in one pass:我建议的是逐行读取文件,一次将其转换为生成的 map:
(require '[clojure.java.io :refer [reader]]
'[clojure.string :as cs]
'[clojure.edn :as edn])
(with-open [rdr (reader "data.csv")]
(into {}
(map (comp (juxt (comp edn/read-string first) rest)
#(cs/split % #"\|")))
(line-seq rdr)))
;;=> {1 ("John Smith" "123 Here Street" "456-4567"),
;; 2 ("Sue Jones" "43 Rose Court Street" "345-7867"),
;; 3 ("Fan Yuhong" "165 Happy Lane" "345-4533")}
notice, you don't have to read the whole file into memory, rather you use with-open
reader + line seq
.注意,您不必将整个文件读入 memory,而是使用
with-open
reader + line seq
。
notice also, the form of into
+ map
(the transducer) is used instead of simple map
then into {}
or for
, to avoid intermediate collection creation.另请注意,使用
into
+ map
(传感器)的形式代替简单的map
然后into {}
或for
,以避免创建中间集合。
You should use a library to read CSV data.您应该使用库来读取 CSV 数据。 Here is another one .
这是另一个。
Here is an example:这是一个例子:
(ns tst.demo.core
(:use tupelo.core tupelo.test)
(:require
[tupelo.csv :as csv]
))
; use (slurp <filename>) to read data into a string
(def data-str
"id|name|address|phone
1|John Smith|123 Here Street|456-4567
2|Sue Jones|43 Rose Court Street|345-7867
3|Fan Yuhong|165 Happy Lane|345-4533 ")
Note that I added a header line to describe the fields of each CSV record.请注意,我添加了一条 header 行来描述每个 CSV 记录的字段。 Unit tests show the result:
单元测试显示结果:
(dotest
(let [entity-maps (csv/parse->entities data-str :delimiter \|)
grouped (group-by :id entity-maps)]
(is= entity-maps
[{:id "1",
:name "John Smith",
:address "123 Here Street",
:phone "456-4567"}
{:id "2",
:name "Sue Jones",
:address "43 Rose Court Street",
:phone "345-7867"}
{:id "3",
:name "Fan Yuhong",
:address "165 Happy Lane",
:phone "345-4533"}])
(is= grouped
{"1"
[{:id "1",
:name "John Smith",
:address "123 Here Street",
:phone "456-4567"}],
"2"
[{:id "2",
:name "Sue Jones",
:address "43 Rose Court Street",
:phone "345-7867"}],
"3"
[{:id "3",
:name "Fan Yuhong",
:address "165 Happy Lane",
:phone "345-4533"}]})))
Be sure to see this list of documentation , especially the Clojure CheatSheet.请务必查看此文档列表,尤其是 Clojure CheatSheet。
(def cust-file ["1|John Smith|123 Here Street|456-4567"
"2|Sue Jones|43 Rose Court Street|345-7867"
"3|Fan Yuhong|165 Happy Lane|345-4533"])
(into {} ;; construc new hash map from coll
;; (into {} ["key" "data"]) => {"key" "data"}
(for [line cust-file ;; `for` instead of `doseq`
;; (`doseq` will return nil, but `for` - results of iteration)
:let [[id & data] ;; shortend `let` alias, use desctructjion to get `id` and rest as `data`
(clojure.string/split line #"\|")]]
[(Integer/parseInt id) data])) ;; return pair [id [name add phone]] for every line
;; => {1 ("John Smith" "123 Here Street" "456-4567"),
;; 2 ("Sue Jones" "43 Rose Court Street" "345-7867"),
;; 3 ("Fan Yuhong" "165 Happy Lane" "345-4533")}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.