简体   繁体   中英

Clojure: how to get an element of a vector in another vector

I am very new to Clojure and am having difficulties understanding the operations of vectors/lists/maps. I am trying to print out the names of all the customers in data, but I cannot figure out how. Please help.

(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))
       )
  )
)

gives me:

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

what I want:

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

What you've got so far (slightly rewritten) is:

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

(str/split-lines data) splits the lines into a sequence of strings:

["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) splits each line into tuples of strings:

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

Now you want to transform each tuple of strings into just the 2nd element of each tuple. There are a couple of functions you could use for that: get or nth (both are zero-based).

For example:

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

You can get a list of names using

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

Then print each name with

(doseq [n names]
  (println n))

I often use sequence and composed transducers to explore data, as it's convenient for building up transformations one step at a time.

You can split each line and get the second column like this

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

and print the result

(map println (test data))

or better using doseq for printing only

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

Using RegEx:

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

returns:

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

Explaining:

re-seq

We ask re-seq to find at each line the first content between a pair of | . The ? in the regex means we want a non greedy search.

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

returns:

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

map

Finally, we use map second to visit each element of the list and get only the second string of the vector.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM