获得类似内容的惯用方法是什么?
((fn [coll] (function-body)) [:a :b :c :d])
-> [[:a :b][:a :c][:a :d][:b :c][:b :d][:c :d]]
我只能这样做。
#(for [i (range (count %))
j (range (inc i) (count %))]
[(nth % i) (nth % j)])
但这很丑陋,而且收藏速度很慢。我想避免循环/重复
答案 0 :(得分:3)
明确使用递归...
(defn pairs [coll]
(if-let [[x & xs] (seq coll)]
(lazy-cat (map #(vector x %) xs) (pairs xs))))
例如,
(pairs [:a :b :c :d])
; ([:a :b] [:a :c] [:a :d] [:b :c] [:b :d] [:c :d])
这是一个懒惰的序列。如果需要,您可以使用vec
将其倒入向量中:我认为最好留给客户做出决定。
答案 1 :(得分:0)
这是一个懒惰的解决方案。
user> (def data [:a :b :c :d])
#'user/data
user> (defn loopy [data]
(lazy-seq (if (seq data)
(cons (map #(vector (first data) %) (rest data))
(loopy (rest data)))
nil)))
#'user/loopy
user> (apply concat (loopy data))
([:a :b] [:a :c] [:a :d] [:b :c] [:b :d] [:c :d])
这会产生一个惰性序列,其中每个元素都是一个懒惰的序列,它将当前元素的向量创建到一个向量中,其中包含其余每个元素。当此段通过调用(apply concat )
为空时,会延迟生成下一个段。
答案 2 :(得分:0)
我找到了解决问题的丑陋管道。我发现它不太优雅,但我还没有能够美化它。
(->> [:a :b :c :d]
(iterate rest)
(take-while not-empty)
(mapcat (fn [[f & r]] (map #(vector f %) r)))
vec)
在给定列表[:a :b :c :d]
时,让我们分析mapcat中的函数。它使用第一个元素:a
计算所有向量,并从[:b :c :d], that is
([:a:b] [:a:c] [:a:d])`中获取第二个元素连续元素。
管道的第一部分构造了原始向量([:a :b :c :d](:b :c :d)(:c :d)(:d) () () () ...)
的所有休止符的序列,该序列在第一个空的休息时停止。
然后mapcat在前面描述的组合函数中插入此列表,最后的vec将序列转换为向量。
通过引入一些辅助功能,这可以更具可读性:
(defn rests [coll]
(take-while not-empty (iterate rest coll)))
(defn pairfirst [[f & r]]
(map #(vector f %) r))
(defn pairs [coll]
(mapcat pairfirst (rests coll)))
答案 3 :(得分:0)
这与Juan Manuel的答案一致,我发现在最后一部分使用列表理解更具可读性。匿名函数为[(first s) x]
(rest s).
l
(defn pairs [xs]
(->> xs
(iterate rest)
(take-while seq)
(mapcat #(for [x (rest %)]
[(first %) x]))))
答案 4 :(得分:0)
for
is already lazy和filter
is too。因此,如果元素具有自然顺序,执行此操作的一种方法是生成笛卡尔乘积,然后按排序顺序进行过滤。
(defn pairs [c]
(->> (for [x c, y c] [x y])
(filter #(apply <= %))))
(def c (range 0 1e7))
(time (nth (pairs c) 0)) ;; ~ 0.07 ms
(time (nth (pairs c) 1e4)) ;; ~ 6 ms
(time (nth (pairs c) 1e7)) ;; ~ 2600 ms
我认为您使用nth
可能会减慢集合迭代的速度:
(def pairs2
#(for [i (range (count %))
j (range (inc i) (count %))]
[(nth % i) (nth % j)]))
(def c (range 0 1e7))
(time (nth (pairs2 c) 0)) ;; ~ 960 ms
(time (nth (pairs2 c) 1e4)) ;; ~ 1514 ms
(time (nth (pairs2 c) 1e7)) ;; ~ ¯\_(ツ)_/¯