如何使用其元素更新记录
(pprint records)
({:Name "John" :Age 12 :Index 123 :Class_Index}
{:Name "Joe" :Age 13 :Index 3 :Class_Index}
{:Name "Jon" :Age 14 :Index 4 :Class_Index})
如何编写一个函数,以便根据age + index更新class_index。同时可以更新记录,以便在运行函数后输出将是
(pprint records)
({:Name "John" :Age 12 :Index 123 :Class_Index 135}
{:Name "Joe" :Age 13 :Index 3 :Class_Index 16}
{:Name "Jon" :Age 14 :Index 4 :Class_Index 18})
但是,我无法手动输入记录的所有元素,因为它会包含太多行。您的答案中的功能是否仍然可以使用? pprint只是为了说明。事实上,我的记录会包含许多元素。
在某种意义上(def记录(原子[记录]))或者我必须遍历那些会占用太多内存的行。有没有更有效的方法来做到这一点。
答案 0 :(得分:2)
如果您要一次更新记录
(def records (atom [(->Record "John" 12 123 nil)
(->Record "Joe" 13 3 nil)
(->Record "Jon" 14 4 nil)]))
(reset! records (map #(assoc % :Class_Index (+ (:Age %) (:Index %)))
@records))
(pprint records)
-> #<Atom@131bf42:
({:Name "John", :Age 12, :Index 123, :Class_Index 135}
{:Name "Joe", :Age 13, :Index 3, :Class_Index 16}
{:Name "Jon", :Age 14, :Index 4, :Class_Index 18})>
否则
(def records [(ref (->Record "John" 12 123 nil))
(ref (->Record "Joe" 13 3 nil))
(ref (->Record "Jon" 14 4 nil))])
(dosync (doseq [record records]
(alter record #(assoc % :Class_Index (+ (:Age %) (:Index %))))))
(pprint records)
-> [#<Ref@178f7a8: {:Name "John", :Age 12, :Index 123, :Class_Index 135}>
#<Ref@129617b: {:Name "Joe", :Age 13, :Index 3, :Class_Index 16}>
#<Ref@ac9126: {:Name "Jon", :Age 14, :Index 4, :Class_Index 18}>]
更新。如果集合中有很多元素,那么最好使用clojure贴图而不是记录对象。只需用地图替换记录定义
(def records (atom [{:Name "John", :Age 12, :Index 123, :Class_Index nil}
{:Name "Joe", :Age 13, :Index 3, :Class_Index nil}
{:Name "Jon", :Age 14, :Index 4, :Class_Index nil}]))
或者是否有物品来源
(def records (atom (source-fn ...)))
在这种情况下,没有内存开销。其余代码也是一样。
答案 1 :(得分:0)
请记住,在Clojure的上下文中,记录是构建地图的一种方式(我想你的意思是来自数据库的记录)。关于你的问题:
; The database
(def people [
{:Name "John" :Age 12 :Index 123}
{:Name "Joe" :Age 13 :Index 3}
{:Name "Jon" :Age 14 :Index 4}])
; Calculates the class index for a person and returns the updated person
(defn class-index [{:keys [Age Index] :as person}]
(assoc person :Class_Index (+ Age Index)))
; Calculate the class index for all people
(pprint (map class-index people))
; Output
; ({:Name "John", :Age 12, :Class_Index 135, :Index 123}
; {:Name "Joe", :Age 13, :Class_Index 16, :Index 3}
; {:Name "Jon", :Age 14, :Class_Index 18, :Index 4})