chaos-theory
chaos-theory

Reputation: 45

How to change few lists inside single hashmap?

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

Answers (2)

Leonid Beschastny
Leonid Beschastny

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

pete23
pete23

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

Related Questions