我想知道进行复杂数据结构更改的惯用方法是什么。这是一个包含列表的hashmap,我想从其中一个列表中移动一些项目到另一个:
输入
{ :a (1 2 3) :b (4 5) }
输出:
{ :a (2 3) :b (4 5 1) }
“第一个元素:a被添加为最后一个:b”
在实践中,我需要这样的结构来代表游戏状态,如:
{ :first_player { :deck (2 3 4 5) :hand (6 1) :discard () }
:second_player { :deck (1 8 9 10) :hand (3) :discard (1 7) }
:board { :first_player_side (1 3) :second_player_side (7 9) }}
正如你所看到的,我需要将卡片ID从不同的列表移动到不同的列表中的不同列表(从手到棋,从棋盘移动到丢弃堆等)。我只是想知道如何以简单/可读的方式制作它。
感谢您的回答。
答案 0 :(得分:3)
Clojure有一个update-in
function,专为进行复杂的数据结构更改而设计:
(defn magic [{:keys [a] :as m}]
(-> m
(update-in [:a] rest)
(update-in [:b] concat (take 1 a))))
或更一般的解决方案:
(defn move-els [m from to numel]
(let [els (take numel (get m from))]
(-> m
(update-in [from] (partial drop numel))
(update-in [to] concat els))))
试一试:
=> (move-els { :a '(1 2 3) :c "foo" :b '(4 5) } :a :b 2)
{:a (3), :c "foo", :b (4 5 1 2)}
答案 1 :(得分:0)
你在寻找地图解构吗?
(defn frob [{:keys [a b]}]
{:a (rest a) :b (conj b (first a))})
当然,这并不是你想要的,因为那不会很有趣。
有关重组的快速概述,请参阅http://blog.jayfields.com/2010/07/clojure-destructuring.html。