Clojure:基于变量动态构造函数?
有关以下数据:Clojure:基于变量动态构造函数?,clojure,higher-order-functions,Clojure,Higher Order Functions,有关以下数据: (def occurrence-data '(["John" "Artesyn" 1 31.0] ["Mike" "FlexPower" 2 31.0] ["John" "Eaton" 1 31.0])) 我想要一个函数: (defn visit-numbers "Produce a map from coordinates to number of customer visits from occurrence records." [coordinates occur
(def occurrence-data '(["John" "Artesyn" 1 31.0] ["Mike" "FlexPower" 2 31.0] ["John" "Eaton" 1 31.0]))
我想要一个函数:
(defn visit-numbers
"Produce a map from coordinates to number of customer visits from occurrence records."
[coordinates occurrences]
(let [selector ??? ; a function that would be equivalent to (juxt #(nth % c1) #(nth % c2) ..), where c1, c2, ... are elements of coordinates
]
(group-by selector occurrences)
)
(def selector (juxt #(nth % 1) #(nth % 3)))
(defn make-selector [& indexes] (apply juxt (map (fn[i] #(nth % i)) indexes)))
例如,对于坐标=[13]
应该是
(group-by (juxt #(nth % 1) #(nth % 3)) occurrence-data)
我想这应该是可能的?我试图使用一些列表表达式,但还没有弄明白
我的实验如下:
(def selector (list 'juxt '#(nth % 1) '#(nth % 3)))
(group-by selector occurrence-data)
出现错误:
java.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to clojure.lang.IFn
core.clj:6600 clojure.core/group-by[fn]
protocols.clj:143 clojure.core.protocols/fn
protocols.clj:19 clojure.core.protocols/fn[fn]
protocols.clj:31 clojure.core.protocols/seq-reduce
protocols.clj:48 clojure.core.protocols/fn
protocols.clj:13 clojure.core.protocols/fn[fn]
core.clj:6289 clojure.core/reduce
core.clj:6602 clojure.core/group-by
我有两个问题要解决:
还是我使用了太复杂的方法来实现我的目标?只需直接调用juxt来创建您的函数,并定义选择器来保存该函数:
(defn visit-numbers
"Produce a map from coordinates to number of customer visits from occurrence records."
[coordinates occurrences]
(let [selector ??? ; a function that would be equivalent to (juxt #(nth % c1) #(nth % c2) ..), where c1, c2, ... are elements of coordinates
]
(group-by selector occurrences)
)
(def selector (juxt #(nth % 1) #(nth % 3)))
(defn make-selector [& indexes] (apply juxt (map (fn[i] #(nth % i)) indexes)))
要动态创建,请创建函数创建函数:
(defn visit-numbers
"Produce a map from coordinates to number of customer visits from occurrence records."
[coordinates occurrences]
(let [selector ??? ; a function that would be equivalent to (juxt #(nth % c1) #(nth % c2) ..), where c1, c2, ... are elements of coordinates
]
(group-by selector occurrences)
)
(def selector (juxt #(nth % 1) #(nth % 3)))
(defn make-selector [& indexes] (apply juxt (map (fn[i] #(nth % i)) indexes)))
REPL示例:
core> (def occurrence-data '(["John" "Artesyn" 1 31.0] ["Mike" "FlexPower" 2 31.0] ["John" "Eaton" 1 31.0]))
#'core/occurrence-data
core> (def selector (juxt #(nth % 1) #(nth % 3)))
#'core/selector
core> (group-by selector occurrence-data)
{["Artesyn" 31.0] [["John" "Artesyn" 1 31.0]], ["FlexPower" 31.0] [["Mike" "FlexPower" 2 31.0]], ["Eaton" 31.0] [["John" "Eaton" 1 31.0]]}
core> (group-by (make-selector 0 1 2) occurrence-data)
{["John" "Artesyn" 1] [["John" "Artesyn" 1 31.0]], ["Mike" "FlexPower" 2] [["Mike" "FlexPower" 2 31.0]], ["John" "Eaton" 1] [["John" "Eaton" 1 31.0]]}
这几乎是
索引
(clojure.set/index occurrence-data [2 3])
;=>
; {{3 31.0, 2 2} #{["Mike" "FlexPower" 2 31.0]},
; {3 31.0, 2 1} #{["John" "Eaton" 1 31.0] ["John" "Artesyn" 1 31.0]}}
例如,您可以看到,在坐标2和3处有两条记录共享相同的值,这些值分别为1和31.0
如果您想去掉索引并映射到计数,那么
(reduce-kv
(fn [a k v] (conj a {(vals k) (count v)}))
{}
(clojure.set/index occurrence-data [2 3]))
;=> {(31.0 1) 2, (31.0 2) 1}
定义
然后比如说,
(group-by-indices [1] occurrence-data)
;{["Artesyn"] [["John" "Artesyn" 1 31.0]],
; ["FlexPower"] [["Mike" "FlexPower" 2 31.0]],
; ["Eaton"] [["John" "Eaton" 1 31.0]]}
及
如果要保留选择映射,请使用
select key
而不是mapv
。然后我们就接近了,也就是说,在其他条件相同的情况下,选择的方法 我认为OP把函数和宏混在一起了。你不需要引用函数体,你的回答忽略了OP问题的第二部分:如何根据一组坐标动态创建这样一个函数。在Clojure中使用关闭坐标的匿名函数进行此操作非常简单。感谢您向我展示现有的解决方案和优雅的简化!谢谢使用mapv或map和group by来实现目标,非常优雅。