Clojure идиоматическое чтение файла на карту - PullRequest
0 голосов
/ 09 сентября 2018

Мне нужно прочитать файл для сопоставления {:v '[] :f '[]}. Я разделяю каждую строку, и если первый элемент "v", то я добавляю оставшуюся часть в v-массив, то же самое для f-массива.

Пример:

v 1.234 3.234 4.2345234
v 2.234 4.235235 6.2345
f 1 1 1

Ожидаемый результат:

{:v [("1.234" "3.234" "4.2345234"), ("2.234" "4.235235" "6.2345")]
 :f [("1" "1" "1")]}

Мой результат:

{:v [("2.234" "4.235235" "6.2345")]
 :f [("1" "1" "1")]}

Вопросы:

  1. Как я могу исправить ошибку? (на карту была добавлена ​​только последняя строка)
  2. Можно ли избежать глобальной переменной (модели) и побочных эффектов?

Код:

(def model
  {:v '[]
   :f '[]})

(defn- file-lines
  [filename]
  (line-seq (io/reader filename)))

(defn- lines-with-data
  [filename]
  (->>
    (file-lines filename)
    (filter not-empty)
    (filter #(not (str/starts-with? % "#")))))

(defn- to-item [data]
  (let [[type & remaining] data]
    (case type
      "v" [:v (conj (:v model) remaining)]
      "f" [:f (conj (:f model) remaining)])))

(defn- fill-model
  [lines]
  (into model
        (for [data lines] (to-item data))))

(defn parse
  [filename]
  (->>
    (lines-with-data filename)
    (map #(str/split % #"\s+"))
    (fill-model)))

1 Ответ

0 голосов
/ 09 сентября 2018

Вы, похоже, отбрасываете изменяющееся состояние вашей модели, вместо этого добавляя данные всех линий в исходную модель с двумя пустыми векторами. Вы можете сохранить состояние своей модели при чтении файла, например, используя reduce:

(defn- add-item [m data]
  (let [[type & remaining] data]
    ;; Updates the model `m` by appending data under the given key.
    ;; In the line below, `(keyword type)` will be :v or :f depending on `type`.
    ;; Returns the updated model.
    (update m (keyword type) conj remaining)))

(defn fill-model [lines]
  ;; Applies `add-item` to the original model and each line of the file
  (reduce add-item model lines)))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...