在Clojure中是否存在迭代二维序列的"正确"方法?假设我有一个数字列表列表,就像这样
((1 2 3)
(4 5 6)
(7 8 9))
Run Code Online (Sandbox Code Playgroud)
我想生成一个新的列表列表,每个数字加1.有没有一种简单的方法在Clojure中执行此操作而不依赖于嵌套映射或循环/重复?我已经能够做到了,但我的解决方案很难看,当我重新阅读它们时,我发现它们很难理解.
谢谢
Ale*_*art 18
你所描述的恰恰clojure.walk
是:
(def matrix [[1 2 3] [4 5 6] [7 8 9]]) (use 'clojure.walk :only [prewalk]) (prewalk #(if (number? %) (inc %) %) matrix) => [[2 3 4] [5 6 7] [8 9 10]]
注1:对于文字顺序集合,使用向量而不是括号是惯用的.
注2:步行保留类型.
Sea*_*lan 14
你总是可以使用列表理解.我发现自己经常使用它们来自命令背景,所以我不知道它是多么惯用.在您的具体情况下,您可以:
(for [my-list my-matrix] (map inc my-list))
Run Code Online (Sandbox Code Playgroud)
Mat*_*ick 10
对于二维情况,您可以执行以下操作:
(map #(map inc %) my-two-d-list)
Run Code Online (Sandbox Code Playgroud)
这不是一件坏事:将函数#(map inc %)
应用于列表中的每个元素.
对于高阶情况,你基本上是在谈论树遍历.您需要一个接受树和函数的函数,并将该函数应用于树中的每个节点.你可以在clojure.walk中找到这个功能.
肖恩和马特的其他答案都显示了获得正确结果的简明而有效的方法.
但是,您可以对此进行一些重要的扩展:
示例代码:
;; general higher order function
(defn map-dimensions [n f coll]
(if (= n 1)
(map f coll)
(map #(map-dimensions (dec n) f %) coll)))
;; use partial application to specialise to 2 dimensions
(def map-2d (partial map-dimensions 2))
(map-2d inc
'((1 2 3)
(4 5 6)
(7 8 9)))
=> ((2 3 4) (5 6 7) (8 9 10))
Run Code Online (Sandbox Code Playgroud)
自core.matrix
2013年推出以来,现在这是处理多维数组操作的更好方法:
(use 'clojure.core.matrix)
(def M [[1 2 3]
[4 5 6]
[7 8 9]])
(emap inc M)
=> [[2 3 4 ]
[5 6 7 ]
[8 9 10]]
Run Code Online (Sandbox Code Playgroud)
使用优点core.matrix
:
transpose
,shape
,reshape
,slice
,subarray
等. 归档时间: |
|
查看次数: |
2690 次 |
最近记录: |