2012-03-09 46 views
13

Nếu bạn có một bản đồ hoặc một bộ sưu tập bản đồ và bạn muốn có thể cập nhật các giá trị của nhiều phím bằng một chức năng, cách thức thành ngữ nhất để thực hiện điều này là gì?Cập nhật giá trị của nhiều phím

=> (def m [{:a 2 :b 3} {:a 2 :b 5}]) 
#'user/m 
=> (map #(update-in % [:a] inc) m) 
({:a 3, :b 3} {:a 3, :b 5}) 

Thay vì lập bản đồ update-in cho mỗi phím, tôi muốn lý tưởng như một số chức năng mà hoạt động như thế này:

=> (map #(update-vals % [:a :b] inc) m) 
({:a 3, :b 4} {:a 3, :b 6}) 

Lời khuyên nào sẽ được nhiều đánh giá cao! Tôi đang cố gắng giảm số lượng dòng trong một tập lệnh dài không cần thiết.

Trả lời

22

Bất cứ khi nào bạn cần phải lặp đi lặp lại áp dụng một fn để một số dữ liệu, reduce là bạn của bạn:

(defn update-vals [map vals f] 
    (reduce #(update-in % [%2] f) map vals)) 

Đây là nó trong hành động:

user> (def m1 {:a 2 :b 3}) 
#'user/m1 
user> (update-vals m1 [:a :b] inc) 
{:a 3, :b 4} 
user> (def m [{:a 2 :b 3} {:a 2 :b 5}]) 
#'user/m 
user> (map #(update-vals % [:a :b] inc) m) 
({:a 3, :b 4} {:a 3, :b 6}) 
+1

Rất đẹp, cảm ơn cho trả lời nhanh quá! – Giles

+0

Tôi tự hỏi nếu có một cách để giữ cho hành vi của cập nhật-in để một khóa thiếu không ném một ngoại lệ con trỏ null. '(update-in {} [: test] (fnil inc 0)) {: test 1}' – Istvan

+0

đây là một câu trả lời hay và làm nổi bật một số vẻ đẹp của việc học clojure (cũng là một số khó khăn trong não không lisper) – zach

Các vấn đề liên quan