使用向量更新记录

时间:2013-01-03 14:29:40

标签: clojure

如何使用其元素更新记录

(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记录(原子[记录]))或者我必须遍历那些会占用太多内存的行。有没有更有效的方法来做到这一点。

2 个答案:

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