经过多年的Java(和PHP/JavaScript)经验,我刚刚开始学习Clojure.真是个挑战:-)
如何以惯用方式更新值的映射?当我map
在地图上使用该函数时,它不返回地图,它返回一个序列.
我正在开发一个小应用程序,我有一个任务列表.我想做的是改变一些单独任务中的一些值,然后更新原始任务列表.以下是我正在测试的任务:
(defrecord Task [key name duration]) (def tasks (atom { "t1" (->Task "t1" "Task 1" 10) "t2" (->Task "t2" "Task 2" 20) "t3" (->Task "t3" "Task 3" 30) } ))
我已经使用字符串键将任务放在散列映射中,因此它可以快速,直接地访问映射中的任何任务.每个任务都包含密钥,因此我知道当我将各个任务传递给其他函数时,关键是什么.
更新我正在使用的持续时间,map
并update-in
迭代并有选择地更新每个任务的持续时间,并返回修改后的任务.
这是功能:
(defn update-task-durations "Update the duration of each task and return the updated tasks" [tasks] ; 1) Why do I have to convert the result of the map function, ; from a sequence then back to a map? (into {} (map (fn [task] (println task) ; debug (update-in task ; 2) Why do I have to use vector index '1' here ; to get the value of the map entry? [1 :duration] (fn [duration] (if (< duration 20) (+ duration 1) (+ duration 2) ) ) ) ) tasks)) )
我用这个打印之前/之后的值:
(println "ORIGINAL tasks:") (println @tasks) (swap! tasks update-task-durations) (println "\nUPDATED tasks:") (println @tasks)
1)我遇到的主要问题是map
函数返回一个序列,而不是一个map,所以我不得不再次将序列转换回一个map,into {}
这对我来说似乎是不必要和低效的.
有一个更好的方法吗?我应该使用除以外的功能map
吗?
我可以更好地安排我的数据结构,同时仍然可以直接访问单个任务吗?
可以使用into {}
?将(可能非常大的)序列转换为地图吗?
2)另外,在我的函数参数中,我传递给map
函数,每个任务都给我map
,作为表格的向量,[key value]
当我期望一个地图条目时,所以从我有的地图条目中获取值将以下键传递给我update-in
[1 :duration]
这看起来有点难看,是否有更好/更清晰的方式来访问映射条目而不是使用向量的索引1?