你如何编写一个函数来记住它在 clojure 中的先前输入

How do you write a function that remembers it's previous input in clojure

所以我在阅读 SO 时遇到了一个学生问题,该问题涉及找到最长的 char 序列,而下一个符号出现在当前符号之后。例如给定一个 "abzbac" 的字符串,输出将是 "abz"。这似乎是一个相当普遍的学习任务。输入为 increasing/decreasing 时取。所以我知道如何以命令的方式做到这一点。您迭代跟踪索引,查看当前索引和下一个索引是否通过谓词。我不知道如何以实用的方式做到这一点。我唯一的猜测是你必须构建一个函数来跟踪之前的输入,并且是一个谓词。在 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 中编写这个函数?

您可以使用 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")))

我也会用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")))

一般来说,您可以通过在函数调用之间保存状态来完成任何操作,也可以通过添加描述先前状态的参数来完成。不同之处在于,通过添加参数,您可以根据需要更灵活地做事,并且如果您可以假设状态不存储在函数中,代码更容易理解和调试。

这里有一些不同的方法。
首先让我们看看我们对序列是否升序感兴趣。这实际上并不是单个值的 属性,而是 值的顺序对 。因此,如果我们可以根据顺序对重新解决问题,那么在每个点我们 都有 我们需要的数据,没有状态。为了制作这些对,我们可以使用 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.