Reputation: 45
I wonder what is the idiomatic way of doing complicated data structures changes. Here is a hashmap that contains lists, i want to take one of those list and move some items to the other one:
input:
{ :a (1 2 3) :b (4 5) }
output:
{ :a (2 3) :b (4 5 1) }
"first element of :a is added as last to :b"
In practice I need such structure to represent game state like:
{ :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) }}
As u can see i will need to move cards ids from different lists to different lists in various hashmaps (play from hand to board, move from board to discard pile etc). I just wonder how to make it in simple/readable way.
Thanks for answers.
Upvotes: 1
Views: 67
Reputation: 51480
Clojure has an update-in
function, designed for doing complicated data structures changes:
(defn magic [{:keys [a] :as m}]
(-> m
(update-in [:a] rest)
(update-in [:b] concat (take 1 a))))
Or more general solution:
(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))))
Try it:
=> (move-els { :a '(1 2 3) :c "foo" :b '(4 5) } :a :b 2)
{:a (3), :c "foo", :b (4 5 1 2)}
Upvotes: 3
Reputation: 2280
Are you looking for map destructuring?
(defn frob [{:keys [a b]}]
{:a (rest a) :b (conj b (first a))})
This doesn't do exactly what you want, of course, because that wouldn't be much fun.
See http://blog.jayfields.com/2010/07/clojure-destructuring.html for a good quick overview of restructuring.
Upvotes: 0