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

如何使用map indexed和vector在Clojure中格式化字符串,clojure,functional-programming,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"

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

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排序

为了实现这一点,我对代码做了哪些更改?

也许吧

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

看起来您的数据中已经有索引:

(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))
猜测:

(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,而忽略原始数据中的序列号


可选地在末尾添加
(到(排序映射中))
,这样您就可以将顺序id映射到值,并保留与哈希映射不同的id顺序。

您的意思是构建一个以id为键的映射吗?请尝试
(输入{}您的输出)
看起来您所要求的内容与您所获得的内容非常接近。是的,我正在尝试将文本文件中的id号分配给作为输出的内容。所以最后我会对它们进行分类easily@manandearth实际上,我现在得到的不符合我的实际输出。此外,我发现将所有内容分配为向量并使用其indexesHello@NikoNyrh获取每个值并不困难,您能否用我的答案更新您的答案,因为我在从文本文件获取数据并对其应用您提到的操作时遇到了一个小问题。您可以使用
slurp
将文件内容作为字符串获取,至少如果使用绝对文件路径。您描述的“输出”不是Clojure数据结构,因此不能由Clojure函数生成。你想把它打印出来吗?也许您想将其插入到排序后的地图中。您能告诉我如何获取(([1[“Austin”“Germany”“34-554567]”)的值,例如[1]给出结果1,[2]给出结果“Austin”等等。有一些函数可以从向量中获取元素,例如
nth
get
。它们也可以作为“函数”操作,例如
([“Austin”“Germany”“34-554567”]1)
计算为
“Germany”
。在您更新的答案中,这是我所理解的。您试图将数据放入名为demo.txt的文件中,然后使用slurp读取该文件。在fmt函数中,您应用了修剪和拆分操作,然后在run defn中,通过将fmt作为参数传递给are映射向量。如果我错了,请纠正我。顺便说一句,我已经有一个f从我读取数据的地方开始创建文件。是否需要创建一个新文件,如demo.txt所示。东西在我头上跳动。我只添加了
spit
,以显示文件的创建。如果您已经有了一个文件,显然不需要它。