【问题标题】:Circularly shifting nested vectors循环移位嵌套向量
【发布时间】:2013-12-28 07:55:51
【问题描述】:

给定一个嵌套向量 A

[[1 2 3] [4 5 6] [7 8 9]]

我的目标是循环移动行和列。

如果我首先考虑单行移位,我会期望

[[7 8 9] [1 2 3] [4 5 6]]

在这种情况下,第三行映射到第一行。

这是通过代码实现的

(defn circles [x i j]
     (swap-rows x i j))

有输入

(circles [[1 2 3] [4 5 6] [7 8 9]] 0 1)

但是,我不确定如何进一步移动列。理想情况下,我想添加到函数圈并能够移动行或列。虽然我不确定对于每个班次选择是否只有两个不同的功能是最简单的。

【问题讨论】:

  • 如果(def v [1 2 3 4]),那么(rest (conj v (first v)) 等于[2 3 4 1]。不能解决您的全部问题,但可能是一个起点。

标签: clojure clojure-contrib


【解决方案1】:
(defn circles [xs i j]
  (letfn [(shift [v n]
            (let [n (- (count v) n)]
              (vec (concat (subvec v n) (subvec v 0 n)))))]
    (let [ys (map #(shift % i) xs)
          j  (- (count xs) j)]
      (vec (concat (drop j ys) (take j ys))))))

例子:

(circles [[1 2 3] [4 5 6] [7 8 9]] 1 1)
;= [[9 7 8] [3 1 2] [6 4 5]]

根据您希望执行此操作的频率、输入向量的大小和要应用的移位,使用core.rrb-vector 可能有意义。 clojure.core.rrb-vector/catvec 是相关函数(您也可以使用clojure.core.rrb-vector/subvec 进行切片,但实际上这里可以使用clojure.core 中的常规subvec,因为catvec 将执行自己的转换。

【讨论】:

  • 班次在哪里定义?我经常看到它,但在任何地方都找不到它的定义?
  • @octopusgrabbus 在这个 sn-p 中,它是由 letfn 形式引入的本地函数 - (letfn [(shift …)] …)
  • Marczyk 感谢您的解释。
【解决方案2】:

你也可以使用cycle:

(defn circle-drop [i coll]
  (->> coll
       cycle
       (drop i)
       (take (count coll))
       vec))

(defn circles [coll i j]
  (let [n (count coll)
        i (- n i)
        j (- n j)]
    (->> coll
         (map #(circle-drop i %))
         (circle-drop j))))

(circles [[1 2 3] [4 5 6] [7 8 9]] 2 1)
;; => [[8 9 7] [2 3 1] [5 6 4]]

【讨论】:

    【解决方案3】:

    core.matrix 中有一个名为rotate 的函数(通用数组/矩阵运算通常是这种情况)

    rotate 的第二个参数允许您选择要旋转的维度(0 表示行,1 表示列)

    (use 'clojure.core.matrix)
    
    (def A [[1 2 3] [4 5 6] [7 8 9]])
    
    (rotate A 0 1)
    => [[4 5 6] [7 8 9] [1 2 3]]
    
    (rotate A 1 1)
    => [[2 3 1] [5 6 4] [8 9 7]]
    

    【讨论】:

      猜你喜欢
      • 2016-12-09
      • 2020-04-03
      • 1970-01-01
      • 1970-01-01
      • 2020-01-29
      • 2013-03-03
      • 2012-11-04
      • 2021-07-29
      相关资源
      最近更新 更多