Clojure:实施"缩进"功能

时间:2016-09-30 12:11:12

标签: clojure

我想实现一个" mix"名为interleave的{​​{1}}和interpose

的确,当你写作

indent

返回

(interleave [1 2 3] ["_" "*"])

但我想要

(1 "_" 2 "*")

所以我写了一个实现这个目标的函数:

(1 "_" 2 "*" 3)

事情是表现很可怕:

(defn indent
  "Mix of clojure.core interleave and interpose functions.
   Indents the second collection in the first one."
  [coll1 coll2]
  (let [n1 (count coll1)
        n2 (count coll2)
        vcoll1 (vec coll1)
        vcoll2 (vec coll2)
        stop-idx (min (- n1 2) (- n2 1))]
    (-> (loop [init '()
               i 0]
          (cond (> i stop-idx)
                  init
                :else
                  (recur (concat init [(vcoll1 i) (vcoll2 i)]) (inc i))))
        (concat [(vcoll1 (inc stop-idx))]))))

对于f =交错:2秒 对于f =缩进:7秒

我试图模仿(time (dotimes [_ 10000000] (doall f [1 2 3] ["_" "*"]))) impl,但最后我有相同的costyly操作(count和vec)。

我能用快速计算看到的唯一想法是编写Java代码......

有什么想法吗?谢谢!

编辑:更快的java方式

它不是Clojure解决方案,但它减少了计算时间

interleave

}

package java_utils;

public class Clojure {

    public static Object[] indent (Object[] coll1 , Object [] coll2) {

        int len1 = coll1.length;
        int len2 = coll2.length;

    int stop_index = Math.min(len1 - 2, len2 - 1);

    Object[] result = new Object[2*(stop_index+1) + 1];

    for (int i = 0 ; i <= stop_index ; i++) {
        result[2*i] = coll1[i];
        result[2*i+1] = coll2[i];
    }

    result[2*stop_index+2] = coll1[stop_index+1];

    return result;
}

对于10M迭代,它以1,7s快速计算。

2 个答案:

答案 0 :(得分:1)

为什么不以interleave为基础?像这样:

(defn indent2 [coll1 coll2]
  (when (seq coll1)
    (cons (first coll1)
          (interleave coll2 (rest coll1)))))

它的性能应该几乎等于交错。

答案 1 :(得分:0)

这些问题通常可以通过创建seq在Clojure中得到最好的解决。通常,seqs需要较少的逻辑来实现,并且它们也很适合Clojure库。

(defn interdent 
  ([seq1 seq2]
   (if (seq seq1)
     (lazy-seq
      (cons (first seq1) (interdent seq2 (rest seq1)))))))

另外,我对你的时间码不太确定。不确定你的例子中有什么f。将有问题的函数替换为f会产生错误。 e.g。

user=> (time (dotimes [_ 10000000] (doall interpose [1 2 3] ["_" "*"])))

ArityException Wrong number of args (3) passed to: core/doall  clojure.lang.AFn.throwArity (AFn.java:429)

我使用以下代码段为代码计时。

user=> (time (dotimes [_ 10000000] (doall (interpose [1 2 3] ["_" "*"]))))

e.g。

user=> (interdent [1 2 3] ["_" "*"])
(1 "_" 2 "*" 3)
user=> (interdent [1 2 3] ["_" "*" ":("])
(1 "_" 2 "*" 3 ":(")
user=> (interdent [1 2 3] ["_" "*" ":)" ":("])
(1 "_" 2 "*" 3 ":)")
相关问题