Clojure - прочитать текстовый файл и ввести его в виде списка

У меня возникли проблемы с некоторыми основными операциями ввода-вывода с использованием Clojure. У меня есть текстовый файл, который мне нужно прочитать, разделенный с помощью "|" символ и введите в список для последующей обработки. Вот содержимое моего текстового файла:

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 -main [] 
(println "Enter an option: \n")

(let [choice (read-line)]
  
  (cond (= choice "1") 
        (let [cust-contents (slurp "file.txt")
              nums-as-strings (clojure.string/split cust-contents #"|")
              numbers (map read-string nums-as-strings)]
              (print numbers)
        ) 
  )
) ) )


(-main)

Я бы подумал, что этот код работает, однако вот ошибка, которую я получаю при запуске моей программы:

(; Execution error at user/eval7923$-main (REPL:11).
; EOF while reading

Может ли кто-нибудь указать мне, где я ошибся и как это исправить?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
107
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Во-первых, у вас не должно быть 2 левых скобок подряд, например ((defn ....

Кроме того, парсинг CSV имеет множество библиотек, позволяющих избавиться от нудного изобретения велосипеда. Мой фаворит проиллюстрирован ниже:

(ns tst.demo.core
  (:use demo.core tupelo.core tupelo.test)
  (:require
    [tupelo.csv :as csv]))

(verify
  ; ***** NOTE *****  most CSV has a header line, which is added below for convenience!
  (let [data-str "id|name|address|phone
                  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 "
        entity-maps (csv/csv->entities data-str {:separator \|})]
    (is= entity-maps
      [{:address "123 Here Street", :id "1", :name "John Smith", :phone "456-4567"}
       {:address "43 Rose Court Street", :id "2", :name "Sue Jones", :phone "345-7867"}
       {:address "165 Happy Lane", :id "3", :name "Fan Yuhong", :phone "345-4533"}])))

Этот модульный тест не включает часть чтения файлов, поскольку это только усложняет модульный тест.

Приведенное выше решение основано на моем любимом шаблонном проекте, в конце которого также есть список источников документации.

Вы можете найти исходный код для tupelo.csv а также модульные тесты.


Чтобы прояснить ваш код, вот очищенная версия:

(verify
  (let [data-str        "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 "
        data-lines      (str/split-lines data-str)
        token-table-str (vec (for [line data-lines]
                               (let [token-strs (str/split line #"\|")]
                                 (mapv str/trim token-strs))))]
    (is= token-table-str
      [["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"]])))

Обратите внимание, что я не анализировал данные после стадии String.

Ответ принят как подходящий

Эта ошибка на самом деле возникает, когда вы вызываете read-string с аргументом " ".

А откуда этот " "? Вы использовали неправильное регулярное выражение в clojure.string/split, вы должны использовать #"\|" вместо #"|".

И даже тогда вы не можете вызывать read-string на всем, так как вскоре он снова вылетит, пытаясь разобрать "456-4567".

Кроме того, закрывающие скобки принадлежат одной и той же строке.

Если ваш файл содержит символы новой строки, вам понадобится clojure.string/split-lines , а если вы также реализуете 2 Display Product Table, 3. Display Sales Table и так далее (я знаю контекст для этого кода), case будет лучше, чем cond.

Вот ваш код с некоторыми улучшениями:

(ns homework.core
  (:require [clojure.string :as s])
  (:gen-class))

(defn -main []
  (println "Enter an option: \n")
  (let [choice (read-line)]
    (case choice
          "1" (->> (s/split-lines (slurp "file.txt"))
                   (mapv #(s/split % #"\|"))
                   println)
          "Wrong number")))

(-main)

Добавьте [clojure-csv/clojure-csv "2.0.1"] к своим lein зависимостям. Сделайте lein deps, чтобы установить его.

Поместить в файл, например. "/home/me/test.csv"

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
(ns csvread
  (:require [clojure-csv.core :as csv]))

(defn parse-table [file]
  (csv/parse-csv (slurp file) :delimiter \|))

(defn parse-table-from-string [s]
  (csv/parse-csv s :delimiter \|))

Примените это:

(parse-table "/home/me/test.csv")
;; => (["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 "])

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

(parse-table-from-string s)

Другие вопросы по теме