计算集合中元素的连续出现次数

时间:2014-05-17 15:03:06

标签: 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]
                 (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 个答案:

答案 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)))