Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/codeigniter/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
习惯地在Clojure中迭代2(或更高)维序列_Clojure - Fatal编程技术网

习惯地在Clojure中迭代2(或更高)维序列

习惯地在Clojure中迭代2(或更高)维序列,clojure,Clojure,在Clojure中,是否有一种“正确”的方法来迭代二维序列? 假设我有一个数字列表,像这样 ((1 2 3) (4 5 6) (7 8 9)) 我想生成一个列表的新列表,每个列表的数字增加一。在Clojure中有没有一种不依赖嵌套映射或循环/递归的简单方法?我能够做到这一点,但我的解决方案很难看,当我重新阅读它们时,我发现它们很难理解 感谢二维案例,您可以执行以下操作: (map #(map inc %) my-two-d-list) 读起来还不错:将函数#(map inc%)应用

在Clojure中,是否有一种“正确”的方法来迭代二维序列? 假设我有一个数字列表,像这样

 ((1 2 3)
  (4 5 6)
  (7 8 9))
我想生成一个列表的新列表,每个列表的数字增加一。在Clojure中有没有一种不依赖嵌套映射或循环/递归的简单方法?我能够做到这一点,但我的解决方案很难看,当我重新阅读它们时,我发现它们很难理解


感谢二维案例,您可以执行以下操作:

(map #(map inc %) my-two-d-list)
读起来还不错:将函数
#(map inc%)
应用于列表中的每个元素


对于高阶情况,您基本上讨论的是树遍历。您需要一个包含树和函数的函数,并将该函数应用于树中的每个节点。您可以在中找到用于此的函数。

您始终可以使用列表理解。我发现自己经常在命令式背景下使用它们,所以我不知道它有多地道。在您的具体情况下,您可以执行以下操作:

(for [my-list my-matrix] (map inc my-list))

肖恩和马特的其他答案都显示了获得正确结果的简洁有效的方法

但是,您可以对此进行一些重要的扩展:

  • 处理更高维度的情况会更好
  • 最好将功能包装在高阶函数中
示例代码:

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

您所描述的正是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]] (def矩阵[[1 2 3] [4 5 6] [7 8 9]]) (使用'clojure.walk:仅限[prewalk]) (预走#(如果(数字%)(inc%)%)矩阵) => [[2 3 4] [5 6 7] [8 9 10]] 注1:对于文字顺序集合,使用向量而不是括号是惯用方法


注2:walk保留类型。

自2013年推出
core.matrix
以来,这是处理多维数组操作的一种更好的方法:

(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]]
使用
core.matrix的优点

  • 干净、惯用的Clojure代码
  • 许多通用的n维数组操作函数-
    转置
    形状
    整形
    切片
    子数组
  • 能够插入高性能阵列实现(例如,对于大型数字阵列)

一个迟来的答案,也许并不确切需要什么:你可以试试。它将返回一个您可以迭代的seq:

(flatten  '((1 2 3)
            (4 5 6)
            (7 8 9)))

user=> (1 2 3 4 5 6 7 8 9)
为了增加矩阵元素并重新组装矩阵:

(partition 3 (map inc (flatten  '((1 2 3)
                                  (4 5 6)
                                  (7 8 9)))))

感谢您提到注释1-我仍然有点不确定何时使用其中一个。Clojure.org上的Clojure备忘单引用了这个答案。我将接受这个答案,尽管其他答案肯定是有效的。这让我觉得这是最短、可读性最强的。应该注意的是,
for
生成了一个惰性序列,因此它只在请求值时“迭代”。不过,看看如何从头开始就可以很有价值。另外,
prewalk
需要一个区分叶节点和分支节点的函数。例如,你不能仅仅给出
inc