在Clojure中对向量实现双循环的惯用方法是什么?

时间:2015-12-24 13:24:57

标签: clojure

我是Clojure的新手,我很难通过数据结构习惯性地实现基本操作。

在Clojure中实现以下代码的惯用方法是什么?

AppBarLayout#setExpanded

2 个答案:

答案 0 :(得分:5)

最简单的(但不是最多的FP-ish)几乎与你的例子相同:

(let [v [1 2 3 4 5 6 7]]
  (mapcat #(map (partial vector (first %)) (rest %))
          (take-while not-empty (iterate rest v))))

这里有更多功能变体来生成所有这些对(它不是基于长度或索引,而是基于尾部迭代):

 ([1 2] [1 3] [1 4] [1 5] [1 6] [1 7] [2 3] [2 4] 
  [2 5] [2 6] [2 7] [3 4] [3 5] [3 6] [3 7] [4 5] 
  [4 6] [4 7] [5 6] [5 7] [6 7])

输出:

doseq

然后只需在(let [v [1 2 3 4 5 6 7] pairs (fn [items-seq] (mapcat #(map (partial vector (first %)) (rest %)) (take-while not-empty (iterate rest items-seq))))] (doseq [[i1 i2] (pairs v)] (println i1 i2))) 中使用这些对就可以产生任何副作用:

doseq

更新:关注@ dg123的回答。这很好,但你可以使用for(let [v [1 2 3 4 5 6 7]] (doseq [[x & xs] (iterate rest v) :while xs y xs] (println "x:" x "y:" y))) 的功能,如解构和守卫,让它变得更好:

iterate

你遍历集合的尾部,但请记住,user> (take 10 (iterate rest [1 2 3 4 5 6 7])) ([1 2 3 4 5 6 7] (2 3 4 5 6 7) (3 4 5 6 7) (4 5 6 7) (5 6 7) (6 7) (7) () () ()) 会产生无限的焦点:

[x & xs]

所以你必须以某种方式限制它只包括非空集合。 解构形式user> (let [[x & xs] [1 2 3 4 5 6]] (println x xs)) 1 (2 3 4 5 6) nil 将参数拆分为第一个参数和其余参数的序列:

xs

当绑定的集合为空或具有单个元素时,nil将为user> (let [[x & xs] [1]] (println x xs)) 1 nil nil

:while

所以你只需使用此功能,在列表理解中使用x后卫。

最后你只为xsProcess

中的每一项构建对(或在这种情况下都会产生一些副作用)

答案 1 :(得分:3)

如何使用map vectoriterate

user=> (def l [1 2 3 4 5])
#'user/l
user=> (map vector l (iterate rest (drop 1 l)))
([1 (2 3 4 5)] [2 (3 4 5)] [3 (4 5)] [4 (5)] [5 ()])

生成每个i索引的值的延迟序列,后跟其所有j个。

然后您可以使用for迭代所需的所有值对,如下所示:

user=> (for [[i js] (map vector l (iterate rest (drop 1 l))) 
             j js] 
         [i j])
([1 2] [1 3] [1 4] [1 5] [2 3] [2 4] [2 5] [3 4] [3 5] [4 5])

如果您想执行IO而不是生成延迟序列,请使用doseq

user=> (doseq [[i js] (map vector l (iterate rest (drop 1 l))) 
               j js] 
         (println (str "i: " i " j: " j)))
i: 1 j: 2
i: 1 j: 3
i: 1 j: 4
i: 1 j: 5
i: 2 j: 3
i: 2 j: 4
i: 2 j: 5
i: 3 j: 4
i: 3 j: 5
i: 4 j: 5
nil