【问题标题】:Clojure idiomatic read file to mapClojure 惯用的读取文件以映射
【发布时间】:2018-09-09 10:22:22
【问题描述】:

我需要读取文件来映射{:v '[] :f '[]}。我分割每一行,如果第一个元素为“v”,那么我将剩余部分添加到 v-array,与 f-array 相同。

例子:

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

【问题讨论】:

    标签: parsing clojure


    【解决方案1】:

    您似乎正在放弃模型的变化状态,而是将所有行的数据附加到带有两个空向量的原始模型。您可以在读取文件时保持模型的状态,例如使用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)))
    

    【讨论】:

      猜你喜欢
      • 2011-10-25
      • 1970-01-01
      • 2012-06-28
      • 1970-01-01
      • 1970-01-01
      • 2013-03-08
      • 1970-01-01
      • 1970-01-01
      • 2021-02-08
      相关资源
      最近更新 更多