5

我对 Clojure 很陌生,并且正在尝试通过移植我的代码之一来学习它,但是我目前遇到了以下问题:

=> lineup
{:c b4|b4|b3|b3, :sg b6|b11|b6|b6, :sf b7|b5|b5|b5, :pf b3|b1|b1|b1, :pg b10|b10|b11|b10}
=> (validate-lineup lineup)
ArityException Wrong number of args (0) passed to: PersistentHashMap  clojure.lang.AFn.throwArity (AFn.java:437)

这是功能:

(defn validate-lineup [lineup]
    (map (fn [position]
        ((hash-map (position 0)
            (map
                (fn [s] (.substring s 1))
                (str/split (position 1) #"\|"))
                ))
        ) lineup))

我正在尝试产生类似以下结果:

{:c {"4" "4" "3" "3"} :sg {"6" "11" "6" "6"} :sf {"7" "5" "5" "5"} ... }

感谢您的帮助,如果我没有以正确的“Lisp”方式编写,请教我如何。

4

1 回答 1

12

你的主要问题在这里:

(fn [position]
  ((hash-map (position 0)
             (map
               (fn [s] (.substring s 1))
               (str/split (position 1) #"\|")))))

您创建哈希映射,然后将其作为函数调用(注意 之前的双括号hash-map)。你可以删除它并得到这个:

(fn [position]
  (hash-map (position 0)
             (map
               (fn [s] (.substring s 1))
               (str/split (position 1) #"\|"))))

这种方式validate-lineup将返回

({:c ("4" "4" "3" "3")} 
 {:sg ("6" "11" "6" "6")} 
 {:sf ("7" "5" "5" "5")} 
 {:pf ("3" "1" "1"` "1")} 
 {:pg ("10" "10" "11" "10")})

但是您需要单个地图,而不是一系列地图。您可以合并它们:

(apply merge (validate-lineup lineup))

一些建议:

使用subs而不是.substring:迭代地图时(fn [s] (subs s 1))
使用解构

(fn [[key value]]
  (hash-map key
             (map
               (fn [s] (subs s 1))
               (str/split value #"\|"))))

有一种巧妙的方法可以使用into函数从对向量创建映射。因此,您可以转换lineup为对的向量,其中对的第一项是键,第二项是数字列表:

(defn validate-lineup [lineup]
  (into {} (map (fn [[key value]]
                    [key
                     (map #(subs s 1) (str/split value #"\|"))])
             lineup)))

您可以通过re-seq解析b4|b4|b3|b3为数字序列:

user=> (re-seq #"\d+" "b1|b2|b3")
("1" "2" "3")

最后,您可以将外部替换mapfor宏:

(defn validate-lineup [lineup]
  (into {} (for [[key value] lineup]
                [key (re-seq #"\d+" value)])))
于 2012-08-05T13:12:10.010 回答