如何在单个hashmap中更改几个列表?

时间:2014-04-21 10:15:46

标签: clojure

我想知道进行复杂数据结构更改的惯用方法是什么。这是一个包含列表的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从不同的列表移动到不同的列表中的不同列表(从手到棋,从棋盘移动到丢弃堆等)。我只是想知道如何以简单/可读的方式制作它。

感谢您的回答。

2 个答案:

答案 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