【问题标题】:Clojure: how to get an element of a vector in another vectorClojure:如何在另一个向量中获取向量的元素
【发布时间】:2018-04-08 19:26:23
【问题描述】:

我是 Clojure 的新手,很难理解向量/列表/映射的操作。我正在尝试打印数据中所有客户的姓名,但我不知道如何。请帮忙。

(def data
"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")

(defn test
[]
  (let [lines       (str/split-lines data)
        line-vecs-1 (mapv #(str/split % #"\|" ) lines)]
       (for [x line-vector-c] (print (line-vector-c 1))
       )
  )
)

给我:

 [2 Sue Jones 43 Rose Court Street 345-7867][2 Sue Jones 43 Rose Court Street 
 345-7867][2 Sue Jones 43 Rose Court Street 345-7867]

我想要什么:

"John Smith"
"Sue Jones"
"Fang Yuhong"

【问题讨论】:

  • 你看过所有其他类似的问题吗?看来你们很多人在同一个班或做同样的作业。点击 Clojure 标签,查看问题,因为这基本上已经回答过几次了。
  • line-vector-c 未定义。此外,for 很懒惰,不推荐用于打印等副作用。请改用doseq
  • 一般来说,最好将数据视为存在于 Clojure 数据结构中,在这种情况下是向量或映射序列。那么问题就分为两个:1. 把数据变成这样的形式;2. 推导出答案。

标签: vector clojure maps


【解决方案1】:

到目前为止,您得到的(稍微重写)是:

(mapv (fn [l]
        (str/split l #"\|"))
      (str/split-lines data))

(str/split-lines data) 将行拆分为字符串序列:

["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"]

(mapv #(str/split % #"\|") lines) 将每一行拆分为字符串元组:

[["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"]]

现在您想将每个字符串元组转换为每个元组的第二个元素。您可以使用几个函数:getnth(都是从零开始的)。

例如:

(mapv (fn [l]
        (get (str/split l #"\|")
             1))
      (str/split-lines data))

【讨论】:

    【解决方案2】:

    您可以使用获取名称列表

    (def names
      (sequence
        (comp
          (map #(str/split % #"\|"))
          (map second))
        (str/split-lines data)))
    

    然后用

    打印每个名字
    (doseq [n names]
      (println n))
    

    我经常使用sequence 和组合转换器来探索数据,因为它便于一次构建转换。

    【讨论】:

      【解决方案3】:

      你可以像这样分割每一行得到第二列

      (defn test [xs]
          (->> (str/split-lines xs)       ;split lines
               (map #(str/split % #"\|")) ;get columns
               (map second)))             ;only the second element of each line
      

      并打印结果

      (map println (test data))
      

      或更好地使用 doseq 仅用于打印

      (doseq [n (test data)]
        (println n))
      

      【讨论】:

        【解决方案4】:

        使用正则表达式:

        (map second (re-seq #"\|(.*?)\|" data))
        

        返回:

        ("John Smith" "Sue Jones" "Fan Yuhong")
        

        解释:

        重新排序

        我们要求re-seq 在每一行查找一对| 之间的第一个内容。正则表达式中的? 表示我们需要非贪婪搜索。

        (re-seq #"\|(.*?)\|" data)
        

        返回:

        (["|John Smith|" "John Smith"] ["|Sue Jones|" "Sue Jones"] ["|Fan Yuhong|" "Fan Yuhong"])
        

        地图

        最后,我们使用map second访问列表的每个元素,只得到向量的第二个字符串。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-01-22
          • 1970-01-01
          • 1970-01-01
          • 2014-02-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-03-05
          相关资源
          最近更新 更多