获得类似内容的惯用方法是什么?
(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)))
答案 0 :(得分: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)
答案 1 :(得分: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
嵌套序列。
答案 2 :(得分:1)
虽然这并未准确提供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]]
答案 3 :(得分:0)
我们可以通过多种方式整理所提供的解决方案:
i
开头的子向量作为外部循环中的参数,而不是索引i
。这使代码更容易理解。 (v j)
代替(nth v j)
来获取j
的{{1}}元素。 v
简化内循环的控制结构。 and
序列以重复值结尾的错误。)这给了我们
dec
这仍然很慢。对于长度为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))]
(recur (subvec v 1) (conj r cc)))
r)))