使用

时间:2018-09-09 05:54:53

标签: parsing clojure

我需要填充地图{:v '[], :f '[]),其中v数组包含以v开头的行中的数据。我该怎么办?

文件示例:

# comment
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)] }

我的尝试:

(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- create-model
  [lines]
  (doseq [data lines]
    (into {:v '[] :f '[]}
          (->>
            (let [[type & remaining] data]
              (case type
                "v" [:v remaining]
                "f" [:f remaining]))))))

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

例外:

user=> (p/parse "test.obj")

IllegalArgumentException Don't know how to create ISeq from: clojure.lang.Keyword  clojure.lang.RT.seqFrom (RT.java:542)

({parse应该是返回结果图)

1 个答案:

答案 0 :(得分:2)

我可以像这样重复您的错误消息:

(into {:v '[] :f '[]} [:v [:a :b]])

我可以按照我的意愿执行程序,如下所示:

(assoc {:v '[] :f '[]} :v [:a :b])
;; => {:v [:a :b], :f []}

在这里,我只是使用[:a :b]而不是remaining。在您的情况下,remaining是一个数字序列,但这并不重要。

对于错误消息,这是一个非常糟糕的消息,应该在以后的Clojure版本中消失。通常是因为您为map提供了一个关键字,而不是可以调用seq的东西。这里的消息来自比我理解的深的地方。

我认为您想要的另一种可行的构造是:

(into {:v '[] :f '[]} [[:v [:a :b]]])

into地图需要一系列地图输入。您忘记包装要放入地图的单个地图条目。我的REPL结果:

{:v [:a :b], :f []}