如何使用map-indexed和vector在Clojure中格式化字符串

时间:2018-05-25 06:56:05

标签: clojure functional-programming

我正在尝试从以下格式的文件中读取内容:

ID |姓名|国家/地区名称|电话号码例如:

1|Austin|Germany|34-554567
2|Mary Jane|Australia|45-78647

我正在使用以下代码从中获取数据:

(
  map-indexed
    #(vector %1 %2)
    (
      map #(vec(.split #"\|" %1))
      (
        line-seq (clojure.java.io/reader "test.txt")
      )
    )
)

使用此代码我得到了这个输出:

([0 ["1" "Austin" "Germany" "34-554567"]] [1 ["2" "Mary Jane" "Australia" "45-78647"]] [2 ["3" "King Kong" "New-Zealand" "35-467533"]])

我希望输出如下:

ID:["name" "country-name" "phone-number"]
ID:["name" "country-name" "phone-number"]

例如:

1:["Austin" "Germany" "34-554567"]
2:["Mary Jane" "Australia" "45-78647"]

其中ID将增加1(从1,2,3开始,依此类推),每个结果都会列出身份或ID,后跟与ID结合的数据,并且应按ID排序。< / p>

我对我的代码做了哪些更改才能实现此目的?

3 个答案:

答案 0 :(得分:0)

也许

(into {}  (map-indexed
       #(vector (inc %1) (rest %2))
       (repeat 2 ["1" "Austin" "Germany" "34-554567"])))

答案 1 :(得分:0)

您的数据看起来已经包含索引:

(def data
  "1|Austin|Germany|34-554567
   2|Mary Jane|Australia|45-78647
   3|King Kong|New-Zealand|35-467533 ")

(defn fmt [line]
  (let [sections (-> line
                     str/trim
                     (str/split #"\|")) ]
    sections) )

(defn run []
  (let [lines (vec (str/split-lines data)) ]
    (mapv fmt lines)))

(run)

结果:

sections => ["1" "Austin" "Germany" "34-554567"]
sections => ["2" "Mary Jane" "Australia" "45-78647"]
sections => ["3" "King Kong" "New-Zealand" "35-467533"]

如果你想丢弃数据中的索引,你可以生成自己的索引:

(defn fmt [idx line]
  (let [sections      (-> line
                          str/trim
                          (str/split #"\|"))
        sections-keep (rest sections)
        result        (apply vector idx sections-keep)]
    result))

(defn run []
  (let [lines (vec (str/split-lines data))]
    (mapv fmt (range 1 1e9) lines)))

更新

如果要使用磁盘文件,请执行以下操作:

(def data
  "1|Austin|Germany|34-554567
   2|Mary Jane|Australia|45-78647
   3|King Kong|New-Zealand|35-467533 ")

(defn fmt [idx line]
  (let [sections      (-> line
                          str/trim
                          (str/split #"\|"))
        sections-keep (rest sections)
        result        (apply vector idx sections-keep)]
    result))

(defn run [filename]
  (let [lines (vec (str/split-lines (slurp filename)))]
    (mapv fmt (range 1 1e9) lines)))

(let [filename "/tmp/demo.txt"]
  (spit filename data)
  (run filename))

答案 2 :(得分:0)

猜测:

(def data
  "1|Austin|Germany|34-554567
   2|Mary Jane|Australia|45-78647
   3|King Kong|New-Zealand|35-467533")

(->> (for [line (clojure.string/split data #"[ ]*[\r\n]+[ ]*")]
       (-> line (clojure.string/split #"\|") rest vec))
     (map vector (rest (range))))

; ([1 ["Austin" "Germany" "34-554567"]]
;  [2 ["Mary Jane" "Australia" "45-78647"]]
;  [3 ["King Kong" "New-Zealand" "35-467533"]])

虽然我不确定您为什么要在结果中显示自动生成的ID,并忽略原始数据中的序列号。

(可选)将(into (sorted-map))添加到末尾,以便将顺序ID映射到值,这样可以保留id顺序,而不像哈希映射。