Clojure:从序列中查找顺序项

时间:2010-04-27 12:04:32

标签: clojure reduce

在Clojure计划中,我有一系列数字:

(2 3 4 6 8 1)

我想找到项目顺序的最长子序列:

(2 3 4)

我假设它会涉及(take-while ...)(reduce ...)

有什么想法吗?

澄清:我需要最长的连续项初始列表。我更确定,更容易。感谢我解决我最初提出的更难的问题。

4 个答案:

答案 0 :(得分:12)

如果您只对最长的初始序列感兴趣,那么它就是1-liner:

(defn longest-initial-sequence [[x :as s]]
  (take-while identity (map #(#{%1} %2) s (iterate inc x))))

答案 1 :(得分:5)

考虑到OP对该问题的评论 - 这完全改变了游戏! - 这可以写得非常简单:

(let [doubletons (partition 2 1 [1 2 3 5 6])
      increment? (fn increment? [[x y]]
                   (== (inc x) y))]
  (cons (ffirst doubletons)
        (map second (take-while increment? doubletons))))

;; returns (1 2 3)

请注意,这实际上是懒惰的。由于当地人清理,我希望不要抓住doubletons的头。另一个版本:

(cons (first [1 2 3 5 6])
      (map second (take-while increment? (partition 2 1 [1 2 3 5 6]))))

问题的原始版本更有趣! :-)可以使用上面的方法构建一个超级简单的解决方案,但当然,与使用reduce相比,性能要低得多。我会看看我是否有与zmila和dnolen的解决方案有很大不同 - 但仍然合理地表现 - 稍后再添加到该线程的那一部分。 (我猜不太可能。)

答案 2 :(得分:4)

回答原文:

(defn conj-if-sequential
  ([] [])
  ([a] a)
  ([a b] (let [a (if (vector? a) a [a])]
           (if (= (inc (last a)) b)
             (conj a b)
             a))))

(reduce conj-if-sequential [2 3 4 6 8 1])

为感兴趣的人提供更通用的解决方案:

(defn sequential-seqs
  ([] [])
  ([a] a)
  ([a b] (let [n (last (last a))]
           (if (and n (= (inc n) b))
             (update-in a [(dec (count a))] conj b)
             (conj a [b])))))

(defn largest
  ([] nil)
  ([a] a)
  ([a b] (if (> (count b) (count a)) b a)))

(reduce largest (reduce sequential-seqs [] [2 3 4 6 8 1 4 5 6 7 8 9 13]))

我认为这要好得多。

答案 3 :(得分:2)

(defn find-max-seq [lst]
  (let [[f & r] lst, 
        longest-seq (fn [a b] (if (> (count a) (count b)) a b)),
        [last-seq max-seq] (reduce 
                             (fn [ [[prev-num & _ :as cur-seq] max-seq] cur-num ]
                               (if (== (inc prev-num) cur-num) 
                                 [(conj cur-seq cur-num) max-seq]
                                 [(list cur-num) (longest-seq cur-seq max-seq)]
                                 ))
                             [(list f) ()]
                             r)]
    (reverse (longest-seq last-seq max-seq))))

(find-max-seq '(2 3 4 6 8 1))  ; ==> (2 3 4) 
(find-max-seq '(3 2 3 4 6 8 9 10 11)) ; ==> (8 9 10 11)