当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《在Clojure中对向量实现双循环的惯用方法是什么?》经验,为你挑选了1个好方法。

我是Clojure的新手,我很难习惯性地使用数据结构实现基本操作.

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

l = [...]
for i in range(len(l)):
  for j in range(i + 1, len(l)):
    print l[i], l[j]

leetwinski.. 5

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

(let [v [1 2 3 4 5 6 7]]
  (doseq [i (range (count v))
          j (range (inc i) (count v))]
    (println (v i) (v j))))

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

(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)))

更新:关注@ dg123的答案.这很好,但是你可以使用doseqfors和解构和保护等功能让它变得更好:

(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会产生一个无限的coll:

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在列表理解中使用guard.

最后你只需构建对(或在这种情况下做一些副作用)x和每个项目xs



1> leetwinski..:

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

(let [v [1 2 3 4 5 6 7]]
  (doseq [i (range (count v))
          j (range (inc i) (count v))]
    (println (v i) (v j))))

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

(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)))

更新:关注@ dg123的答案.这很好,但是你可以使用doseqfors和解构和保护等功能让它变得更好:

(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会产生一个无限的coll:

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在列表理解中使用guard.

最后你只需构建对(或在这种情况下做一些副作用)x和每个项目xs

推荐阅读
135369一生真爱_890
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有