首页 > 解决方案 > 如何实现嵌套 for 循环,将 2D 数组中的每个元素转换为 Clojure 中的零

问题描述

我希望(在 Clojure 中)实现一个嵌套的 for 循环,它将二维数组中的每个元素都转换为零。就像下面写的 C 代码一样。

void set_to_zero(int n, int m[v][v]) {
          int i, j;
          for(i = 0; i < n; i++)
            for(j = 0; j < n; j++)
              m[i][j] = 0;
        }

这是我能够做到的

(defn trial [n m]
  (loop [i 0
         j 0]
    (if (= i (count (range n)))
      (println m)
      (if (= j (count (range n)))
        (recur i j)
        (assoc-in m[i j] 0)
        )
      )
    )
  )

这就是我得到的:即只有一个元素发生了变化,其余的保持不变。

(trial 4 [[9 8 2 3][8 4 5 6][6 1 8 9][3 1 8 9]])
=> [[0 8 2 3] [8 4 5 6] [6 1 8 9] [3 1 8 9]]

更新

(defn trial [n m]
  (for [i (range n)
         j (range n)]
    (if (> i n)
      m
      (if-not (> j n)
        ;(recur (inc i) j)
        (assoc-in m[i j] 0)
        ;(println i j)
        )
      )
    )
  )

新结果

(trial 4 [[9 8 2 3][8 4 5 6][6 1 8 9][3 1 8 9]])
=>
([[0 8 2 3] [8 4 5 6] [6 1 8 9] [3 1 8 9]]
 [[9 0 2 3] [8 4 5 6] [6 1 8 9] [3 1 8 9]]
 [[9 8 0 3] [8 4 5 6] [6 1 8 9] [3 1 8 9]]
 [[9 8 2 0] [8 4 5 6] [6 1 8 9] [3 1 8 9]]
 [[9 8 2 3] [0 4 5 6] [6 1 8 9] [3 1 8 9]]
 [[9 8 2 3] [8 0 5 6] [6 1 8 9] [3 1 8 9]]
 [[9 8 2 3] [8 4 0 6] [6 1 8 9] [3 1 8 9]]
 [[9 8 2 3] [8 4 5 0] [6 1 8 9] [3 1 8 9]]
 [[9 8 2 3] [8 4 5 6] [0 1 8 9] [3 1 8 9]]
 [[9 8 2 3] [8 4 5 6] [6 0 8 9] [3 1 8 9]]
 [[9 8 2 3] [8 4 5 6] [6 1 0 9] [3 1 8 9]]
 [[9 8 2 3] [8 4 5 6] [6 1 8 0] [3 1 8 9]]
 [[9 8 2 3] [8 4 5 6] [6 1 8 9] [0 1 8 9]]
 [[9 8 2 3] [8 4 5 6] [6 1 8 9] [3 0 8 9]]
 [[9 8 2 3] [8 4 5 6] [6 1 8 9] [3 1 0 9]]
 [[9 8 2 3] [8 4 5 6] [6 1 8 9] [3 1 8 0]])

目前,它将所有元素更改为 0,但它是否单独希望它作为一个所有元素都等于 0 的数组返回。

PS 我确信有更有效的方法可以在 2D 向量中实现全零,但我对 for 循环方法特别感兴趣,因为它在其他语言中很流行,并且可以帮助人们更轻松地将其他语言的代码翻译成 Clojure(在某些例)。

谢谢。

标签: for-loopclojurenested-loops

解决方案


Since you already have the sizes of the structure (its a vector of vectors) I think there is no need to pass in any sizes. So the one thing to make sure is to keep the vectors (many tools in the clojure belt use (lazy) sequences).

Using mapv does that. The function to map with can be (constantly 0). Then map that again over the outer vector. E.g.

Plain clojure:

(mapv (partial mapv (constantly 0)) [[9 8 2 3][8 4 5 6][6 1 8 9][3 1 8 9]])
; → [[0 0 0 0] [0 0 0 0] [0 0 0 0] [0 0 0 0]]

Alternative:

Using specter:

(setval [ALL ALL] 0 [[9 8 2 3][8 4 5 6][6 1 8 9][3 1 8 9]])
; → [[0 0 0 0] [0 0 0 0] [0 0 0 0] [0 0 0 0]]

推荐阅读