2

得到这样的东西的惯用方法是什么?

(fn [coll] (function body) [1 0 -1 -1 -1 0 0 0 0 1 1 1 1 1 0 1 -1])
-> [1 1 3 2 1 4 3 2 1 5 4 3 2 1 1 1 1]

我只能这样做。

(fn [coll] 
  (loop [i 0 r []]
    (if (< i (count coll))
      (let [elem (nth coll i)
            cc (loop [j 1]
                 (if (< (+ i j) (dec (count coll)))
                   (let [nelem (nth coll (+ i j))]
                     (if (= elem nelem)
                       (recur (inc j))
                       j))
                   j))]
        (recur (inc i) (conj r cc)))
      r)))
4

4 回答 4

4

修改@noisesmith 的巧妙解决方案来解决我们认为的问题:

(defn countdown-runs [s]
  (->> s
       (partition-by identity)
       (map count)
       (mapcat #(range % 0 -1))))

例如,

(countdown-runs [1 0 -1 -1 -1 0 0 0 0 1 1 1 1 1 0 1 -1])
; (1 1 3 2 1 4 3 2 1 5 4 3 2 1 1 1 1)
于 2014-05-17T16:30:32.903 回答
2

假设你的输出是你想要的,答案应该是

(mapcat #(reverse (range 1 (inc %)))
      (map count (partition-by identity [1 0 -1 -1 -1 0 0 0 0 1 1 1 1 1 0 1 -1])))

先做

(map count (partition-by identity [1 0 -1 -1 -1 0 0 0 0 1 1 1 1 1 0 1 -1]))

获取每个连续元素的计数,然后对于每个计数,提供一个从数字倒数到 1 的列表。然后mapcat将嵌套序列放在一起。

于 2014-05-17T15:57:24.940 回答
2

尽管这并不能准确提供 OP 所要求的内容,但在寻找一种计算集合中连续元素的方法时,您可能最终会出现在此页面上。

使用 Clojure 1.8 中的传感器,我们可以执行以下操作:

(defn runs
  ([]
   (runs identity))
  ([f]
   (comp (partition-by f)
         (map (juxt (comp f first) count))))
  ([f xs]
   (into [] (runs f) xs)))

这将允许我们使用给定的分区函数创建一个转换器,或者在使用分区函数和集合调用时返回一个已实现值的向量。

其使用示例:

(runs :name [{:name "John" :age 22}
             {:name "John" :age 44}
             {:name "Mary" :age 33}
             {:name "Lee" :age 99}
             {:name "Lee" :age 55}])

;; => [["John" 2] ["Mary" 1] ["Lee" 2]]
于 2017-03-08T17:36:27.957 回答
0

我们可以通过多种方式整理所提供的解决方案:

  • 而不是 index i,使用开始的子向量i作为外循环中的参数。这使得代码更容易理解。
  • 为简洁起见,使用(v j)而不是(nth v j)获取 的j第 th 个元素v
  • 用于and简化内循环的控制结构。
  • (并且 - 当我们这样做时 - 删除dec导致以重复值结尾的序列的一次性错误。)

这给了我们

(defn op-s [v] 
  (loop [v v, r []]
    (if (seq v)
      (let [elem (v 0)
            cc (loop [j 1]
                 (if (and (< j (count v)) (= elem (v j)))
                   (recur (inc j))
                   j))]
        (recur (subvec v 1) (conj r cc)))
      r)))

这仍然可能很慢。对于长度为 n 的运行,它执行大约 n 2 /2 次内部循环。我们可以加快速度。一旦我们找到一个运行,我们可以从它的长度倒数,就像惰性版本一样。

(defn op-s [v] 
  (loop [v v, r []]
    (if (seq v)
      (let [elem (v 0)
            cc (loop [j 1]
                 (if (and (< j (count v)) (= elem (v j)))
                   (recur (inc j))
                   j))
            rr (loop [r r, i cc] (case i, 0 r, (recur (conj r i) (dec i))))]
        (recur (subvec v cc) rr))
      r)))
于 2014-05-17T17:00:08.130 回答