Home > OS >  How to retrieve a line as a list instead of a string?
How to retrieve a line as a list instead of a string?

Time:11-07

I'm a newbie using the Clojure language, but I got really stuck with the following problem working with text files. Here's an example of what I am trying to do:

I have a file (backend.txt) that contains a matrix:

((A 10 "Ciel" 10)
(B 15 "Sprite" 10)
(C 20 "Coca-Cola" 10)
(D 12 "Fuze-Tea" 10)
(E 50 "Hattori-Sake" 10)
(F 40 "02Linn-Soju" 10)
(G 16 "Fanta" 10)
(H 25 "Canada-Dry" 10)
(A12 54 "Cigarros" 10)
(Kiero 78 "Calculadora" 10))

I also have the following "locate" function:

(defn locate [token filename]
(with-open [rdr (clojure.java.io/reader filename)]
  (let [line-no (atom 0)
        result (filter #(.contains % token)
                       (line-seq rdr))]
    (if result
      (-> result first)
      nil))))

Basically, the "locate" function takes two arguments, a token and a filename, and returns the first line in the file that contains the token.

(locate "Cigarros" "backend.txt")
> (A12 54 "Cigarros" 10)

The outcome of (locate "Cigarros" "backend.txt") is a string:

(string? (locate "Cigarros" "backend.txt")
>true

I convert it into a seq by using the "read-string" method.

(read-string (locate "Cigarros" "backend.txt"))
>(A12 54 Cigarros 10)
(seq? (read-string (locate "Cigarros" "backend.txt")))
>true

However, notice that Cigarros no longer has the double quotes, and it's really critical that those double quotes remain because by removing them it messes with other functions in my script. So how can I preserve them?

What I expect is to convert the string from the outcome of (locate "Cigarros" "backend.txt") to a list like this:

(A12 54 "Cigarros" 10)
;; (seq? (A12 54 "Cigarros" 10))
;; > true

I hope I made myself clear, and not sounding confusing.

Thanks in advance.

CodePudding user response:

The double quotes should be there - in other words, Cigarros should still be a string. It's just that whatever you're using as your REPL doesn't print them.

Here's how it looks on my end:

(def s "(A12 54 \"Cigarros\" 10)")
=> #'dev/s
(read-string s)
=> (A12 54 "Cigarros" 10)

You can validate that you have a string there by executing (string? (nth (read-string s) 2)).

Also note that a better approach might be to read the file as a proper EDN data structure and then filter it.

  • Related