我正在https://iloveponies.github.io/120-hour-epic-sax-marathon/one-function-to-rule-them-all.html上练习练习7。我有一个解决方案,但因为预期的输出是一个列表,我不得不为我的一些输出添加“反向”。这看起来有点笨拙。
这是我的代码:
(defn insert [sorted-seq n]
(loop [output ()
my-seq sorted-seq]
(cond
(nil? (first my-seq))
(conj output n)
(nil? (first (rest my-seq)))
(reverse (conj output (first my-seq) n))
:else
(if (> (first (rest my-seq)) n (first my-seq))
(reverse (apply conj output (first my-seq) n (rest my-seq)))
(recur (conj output (first my-seq)) (rest my-seq))))))
(insert [] 2) ;=> (2)
(insert [1 3 4] 2) ;=> (1 2 3 4)
(insert [1] 2) ;=> (1 2)
有没有更好的方法来写这个更高效,而不需要反转输出?此外,前两个条件似乎很笨拙。还有更好的方法吗?
答案 0 :(得分:3)
@ A.Webb的解决方案是您正在寻找的解决方案,但将此留给未来的访问者。
我认为你略微过分复杂了这个问题。
一般的想法是:
你可以使用split-with组合1和2,它将序列分成两部分:一部分谓词为真,另一部分为假。
所以,说起clojure:
(defn insert [coll n]
(let [[l r] (split-with #(< % n) coll)]
(concat l [n] r))
答案 1 :(得分:1)
我认为练习的目的是使用递归,而不是产生最惯用的代码。您可以使用向右conj
向量的数据结构来避免逆转。
(defn insert [sorted-seq n]
(loop [s sorted-seq, a []]
(cond
(empty? s) (conj a n)
(< (first s) n) (recur (rest s) (conj a (first s)))
:else (apply conj a n s))))
答案 2 :(得分:0)
如果您准备采用适当的递归,您可以使用列表完成此操作:
(defn insert [ss n]
(if (empty? ss)
(list n)
(let [[x & xs] ss]
(if (< n x)
(cons n ss)
(cons x (insert xs n))))))
lazy-seq
中
没有吹栈的序列。