所以我正在读SO而且我遇到了一个学生问题,其中包括找到最长的char序列,而下一个符号出现在当前的一个之后。例如,给定一串“abzbac”,输出将是“abz”。这似乎是一项相当普遍的学习任务。在输入增加/减少的同时进行。所以我知道如何以命令的方式做到这一点。迭代跟踪索引,查看当前索引和下一个是否传递谓词。我不知道如何以功能的方式做到这一点。我唯一的猜测是你必须构建一个跟踪之前输入的函数,并且是一个谓词。在python中,我认为它看起来像这样。
def passTheTest(x):
def current(y):
temp = y == x # or w/e your comparison is
x = y # saves state for the next go around
return temp
你如何在clojure中编写这个函数?
答案 0 :(得分:4)
这是一种不同的方法
让我们首先看到我们对序列是否在升序感兴趣。这不是单个值的属性,而是连续的值对。因此,如果我们可以根据顺序对重新解决问题,那么在每个点我们拥有我们需要的数据,没有状态。为了制作这些对,我们可以使用partition
每次获取2个值,但是以1为步长。例如,(partition 2 1 "abzbac")
为我们提供((\a \b) (\b \z) (\z \b) ...
现在我们常用的映射,过滤器等再次工作:
(defn longest-increasing [the-str]
(let [pairs (partition 2 1 the-str) ;;Divide the string into the sequential pairs
directioned (partition-by (comp neg? (partial apply compare)) pairs) ;;Group pairs by whether the second char is "higher" or "lower"
ascending (filter #(neg? (apply compare (first %))) directioned) ;Filter out any descending sequences
longest (apply (partial max-key count) ascending)] ;;take the longest sequence
(clojure.string/join (cons (ffirst longest) (map second longest))))) ;;Glue it back together.
答案 1 :(得分:2)
我也会使用reduce,但我认为这有点清楚。
;; rebuild a string from a vector of char
(apply str
;; get run from [run acc]
(first
(reduce
(fn [[run acc] ele]
;; add to acc if ascending
(let [acc' (if (pos? (compare ele (peek acc)))
(conj acc ele)
[ele])
;; replace run if acc is longer
run' (max-key count run acc')]
[run' acc']))
[[] [Character/MAX_VALUE]]
"abzabczab")))
通常,通过在函数调用之间保存状态可以执行的任何操作也可以通过添加描述先前状态的参数来完成。不同之处在于,如果需要,您可以更灵活地执行操作,如果您可以假设状态未存储在函数中,则代码更易于理解和调试。
答案 2 :(得分:0)
您可以使用reduce
:
(apply str (:max-coll
(reduce (fn [{:keys [max-coll coll]} e]
(let [coll' (if (>= 0 (compare (peek coll) e) )
(conj coll e)
[e])]
{:coll coll'
:max-coll (if (<= (count max-coll) (count coll'))
coll'
max-coll)}))
{:max-coll [] :coll []}
"abyzbac")))