我有一个递归函数,每次调用时都会抛出一个哈希值。
第一次循环哈希是:
{1 "mary", 2 "dean"}
下一轮吐出
{23 "ava", 4 "scout"}
并且最后一轮返回
{3 "bina", 16 "bob"}
我的功能将始终返回最后一轮数据,{3" gina",16" bob"}。 我想,不是吐出最后一块数据,而是将它们全部存储在一个巨大的哈希中,以便我可以比较它们。在比较它们之后,函数应该返回" ava",因为这是与最高键相关联的值。最好的方法是什么?
答案 0 :(得分:1)
一种通用模式是向递归函数添加状态参数,并提供添加初始状态值的函数的arity。然后在基本情况下,您可以对状态值进行后处理。
这是一个将第一个奇数之前的输入映射构建为随机值的示例:
user> (defn example
([input] (example input {})) ;; one argument recurs with default value
([input state] ;; two arg case passes the state.
(if (odd? (first input))
state
(recur (rest input)
(assoc state (first input) (rand-int 10))))))
#'user/example
从结果状态中选择最高值的那个:
user> (example [2 4 8 9])
{8 0, 4 1, 2 4}
user> (defn example
([input] (example input {}))
([input state]
(if (odd? (first input))
(first (sort-by val state))
(recur (rest input)
(assoc state (first input) (rand-int 10))))))
#'user/example
user> (example [2 4 8 9])
[8 6]
答案 1 :(得分:1)
如果您有一个副作用函数,它会吐出一系列值,请将其建模为序列。如果序列终止,则可能该函数返回无效值。
功能
(defn ensequence [f! valid?]
(take-while valid? (repeatedly f!)))
...返回由副作用函数f!
生成的值序列,每当valid?
测试失败时终止。
例如,
(ensequence #(rand-int 10) #(not= 5 %))
...在(range 10)
中返回一系列随机值,在第一个5
之前停止:
(6 9)
...例如(你的milage 将变化)。
为了说明ensequence
如何在你的情况下工作,我们使用一个反函数将一个序列转换为一个返回其连续元素的函数,然后nil
:
(defn oracle! [coll]
(let [s (atom coll)]
(fn [] (let [x (first @s)] (swap! s rest) x))))
例如,
(repeatedly 10 (oracle! (range 5)))
;(0 1 2 3 4 nil nil nil nil nil)
为您的数据
(def data [{1 "mary", 2 "dean"} {23 "ava", 4 "scout"} {3 "bina", 16 "bob"}])
功能
(oracle! data)
...依次返回其元素,然后是nil
s:
(repeatedly 10 (oracle! data))
;({1 "mary", 2 "dean"} {23 "ava", 4 "scout"} {3 "bina", 16 "bob"}
nil nil nil nil nil nil nil)
我们可以使用ensequence
来生成它,以恢复原始序列:
(ensequence (oracle! data) identity)
;({1 "mary", 2 "dean"} {23 "ava", 4 "scout"} {3 "bina", 16 "bob"})
由于nil
为false且在此处永不有效,identity
是一个很好的有效性测试。
现在我们有了序列,我们可以随心所欲地做任何事情。在你的情况下,我们只是
key
的条目;和val
。因此:
(val (apply max-key key (reduce concat data)))
;"ava"
我们应该使用(ensequence (oracle! data) identity)
而不是等效的data
,但它没有任何区别。