Clojure 计数集合中元素的连续出现次数
得到这样的东西的惯用方法是什么Clojure 计数集合中元素的连续出现次数,clojure,nested-loops,find-occurrences,Clojure,Nested Loops,Find Occurrences,得到这样的东西的惯用方法是什么 (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
(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)))
(fn[coll]
(循环[i 0 r[]
(如果(
假设您的输出是您想要的,答案应该是
(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
将嵌套序列放在一起。修改@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)
我们可以通过以下几种方式整理提供的解决方案:
- 使用从
开始的子向量作为外循环中的参数,而不是索引i
。这使得代码更容易理解李>i
- 为简洁起见,请使用
而不是(vj)
来获取(nth vj)
的v
第th个元素李>j
- 使用
简化内环的控制结构李>和
- (并且-在我们进行此操作时-删除导致一次性事件的
) 以重复值结尾的序列的错误。)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)))
(定义op-s[v]
(循环[v,r[]
(如有)(续五)
(let[elem(v0)
cc(循环[j 1]
(如果(和(
这仍然是缓慢的。对于长度为n的运行,它执行大约n2/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)))
(定义op-s[v]
(循环[v,r[]
(如有)(续五)
(let[elem(v0)
cc(循环[j 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]]
答案当然应该是
(131451111)
。没有?我的英语肯定不完美,但我的代码完全符合我对他的期望。也许我的描述不好。我只想比较项目后面的元素。建议的开场白:如何将序列映射到项目前面相等项目的计数,包括项目本身?更正:省略第6行中的dec
。当序列在重复项上结束时,它会导致开关错误:在[11]
上,它会产生[11]
。请使用(mapcat)(reverse…)
而不是(flatte)(map#(reverse…)
,flatte几乎总是错误的,因为它可以很容易地破坏输入的嵌套结构。它通常可以(在本例中)替换为mapcat。另一个提示:(这里的样式而不是准确性)-为了更习惯,您可以将(+1%)
替换为(inc%)
-相同数量的字符,但用法更清楚。