Clojure 序列的最大值,其值由键函数确定,其中键返回向量
继续使用Udacity基于python的CS212并翻译成Clojure的过程,我正在尝试编写一个函数:Clojure 序列的最大值,其值由键函数确定,其中键返回向量,clojure,Clojure,继续使用Udacity基于python的CS212并翻译成Clojure的过程,我正在尝试编写一个函数: 返回序列中的所有项 等于序列的最大值 使用返回向量的“键”函数 Clojure's几乎做到了这一点,除了它需要我的键返回一个整数,在本例中,我不返回一个向量。经过一些修改,我可以使用compare函数来比较键控函数返回的向量: (defn all-max-key "Returns a vector of x for which (k x), arbitrated by compare,
(defn all-max-key
"Returns a vector of x for which (k x), arbitrated by compare, are greatest."
([k x] x)
([k x y] (if (= 1 (compare (k x) (k y))) x y))
([k x y & more]
(reduce #(all-max-key k %1 %2) (all-max-key k x y) more)))
现在的问题是,这并没有考虑到关系(其中比较返回0)。换句话说,我的列表中的所有元素都是唯一的,但有些元素的每个键控函数的值可能相等。在命令式世界中,我可能会在列表中循环,跟踪我的最大值,将每个元素与之进行比较,然后在执行时附加/替换一个可变列表
但我觉得必须有一种惯用的、优雅的、功能性的方法来实现这一点,而不必求助于循环。我使用reduce的尝试都导致了将序列与成员元素进行无意义的比较。有人能照亮它吗?这将返回最大项的向量:
(defn maximal-key [k x & xs]
(reduce (fn [ys x]
(let [c (compare (k x) (k (peek ys)))]
(cond
(pos? c) [x]
(neg? c) ys
:else (conj ys x))))
[x]
xs))
在REPL进行测试:
;; convoluted key function to demonstrate that vector keys are fine
user> (maximal-key #(vector (first %))
(list 1 2 3) (list 4 5 6) (list 3 6 8)
(list 4 7 9) (list 1 5 9))
[(4 5 6) (4 7 9)]
请注意,
compare
可能返回一个任意的正整数,以指示其第一个参数大于第二个参数——因此,pos?
取代了==1
这正是我所希望的答案。我不确定我是否仍然完全理解它——特别是[YSX]是如何被分解的,但我认为这将需要我做一些面条。peek对我来说也是新事物。感谢您减少了处理集合的代码。我看到的很多例子都是琐碎的(reduce+[1,2,3]),很高兴听到这些!这里实际上不涉及解构,[ysx]
是归约函数的参数向量。在缩减的每一步中,ys
参数将保存累加器的当前值,累加器是迄今为止处理的输入片段中最大的所有项的向量,x
将是当前正在处理的项。如果当前元素大于先前最大元素的最后一个(因此是所有),则使用它初始化新累加器;如果比较相等,则将其添加到累加器中;否则它就会被丢弃,这就更有意义了。谢谢你的解释!