Clojure 重排序函数

Clojure re-order function

我必须承认这仍然是我 clojure 新手的地方。我经常发现,如果我在 Clojure 文档中搜索,我会找到我正在寻找的函数。 ;)

但我对这个很紧张,但也许我会走运。

我有一个纸牌游戏。每个玩家手中有 1-9 张牌。

通过抽牌从牌组顶开始将牌一次放入一张牌。

玩家要求的是能够将 UNORGANIZED 手牌或 UNSORTED 手牌带到那里并重新组织他们的手牌。

我提供了一个解决方案“在命令 window 中使用 /re-order 31487652 这样的命令怎么样,它可以发出函数(不用担心命令,它只是排序函数)。

这样做的目标是拿走他们手中的每张牌 12345678 并将顺序更改为他们提供的新顺序,即 31487652。

数据格式如下:

(:hand player)

[{:name : "Troll", :_id : 39485723},
{:name : "Ranger", :_id : 87463293},
{:name : "Archer", :_id : 78462721},
{:name : "Orc", :_id : 12346732},
{:name : "Orc", :_id : 13445130},
{:name : "Spell", :_id : 23429900},
{:name : "Dagger", :_id : 44573321}]

我唯一的问题是,我可以使用传统编程语言来思考这个问题,我的意思是很简单,您只需将数据复制到另一个数组,哈哈,但我的意思是我们不喜欢 clojure 吗?...

但我想保持纯粹的 clojure 意识形态,并学习如何做这样的事情。我的意思是,如果它只是 "Use this function",我想那很好,但我不想创建一个原子,除非是强制性的,但我认为情况并非如此。

如果有人可以帮助我开始思考使用 clojure 解决这个问题的方法,那就太棒了!

感谢任何 help/advice/answer...

附录 #1

(defn vec-order [n]
  (into [] (if (pos? n)
             (conj (vec-order (quot n 10)) (mod n 10) )
             [])))

(defn new-index [index new-order] (.indexOf new-order (inc index)))

(defn re-order [state side value]
  (println (get-in @state [side :hand]))
  (update @state [side :hand]
          (fn [hand]
            (->> hand
                 (map-indexed (fn [index card] [(new-index index (vec-order value)) card]))
                 (sort-by first)
                 (mapv second))))
  (println (get-in @state [side :hand])))

这是我当前的代码,其中包含数据提取。有一个巨大的@state,玩家在一边。我使用:

(println (get-in @state [side :hand]))

查看defn执行前后的数据,但我没有得到任何变化。为简单起见,向量为 [2 1 4 3 6 5 8 7].

中的 21436587

但我遗漏了一些东西,因为我什至 运行 /重新订购 12345678 以确保东西没有移动,我只是没有看到东西。但是什么都没有...

谢谢你,让我走到这一步。

因此,注意的第一个函数将是 update,这将使我们能够 return 一个新玩家,如果我们这样调用它,它会应用一个函数。

(update player :hand (fn [hand] ... ))

一旦我们有了这个基本结构,下一个对我们有帮助的函数是map-indexed,它将允许我们将当前手牌与新的排序索引配对。

从那里,我们将能够sort-by the index, and finally mapv取回卡片。

因此,最终结构将类似于:

(defn sort-hand [player new-order]
  (update
    player
    :hand
    (fn [hand]
     (->> hand 
          (map-indexed (fn [index card] [(new-index index new-order) card]))
          (sort-by first)
          (mapv second)))))

为了使其工作,预计 new-order 是一个类似于 [3 1 4 8 7 6 5 2]

的向量

至于new-index,

的解决方法

我们可以这样使用 .indexOf (defn new-index [index new-order] (.indexOf new-order (inc index)))

如果您将所需的元素顺序作为向量,您可以 sort-by 通过返回该向量中卡片索引的函数:

(let [cards [1 2 3 4 5 6 7 8]
      my-order [3 1 4 8 7 6 5 2]]
  (sort-by #(.indexOf my-order %) cards))
;; => (3 1 4 8 7 6 5 2)

在您的帮助下:

(defn vec-order [n]
  (into [] (if (pos? n)
             (conj (vec-order (quot n 10)) (mod n 10) )
             [])))

(defn new-index [new-order index] (.indexOf new-order (inc index)))

(defn re-order [state side value]
  (swap! state update-in [side :hand]
             (fn [hand]
               (->> hand
                    (map-indexed (fn [index card] [(new-index (vec-order value) index) card]))
                    (sort-by first)
                    (mapv second)))))

成功了!!! 100%