1、一个高阶函数的使用:将db查询结果日期进行format,并且group和求sum,重新组织结构
从DB中查到的map结果集如下:
(alk-wxapi.db.db-patient/get-patient-cost
{:page 0,
:size 10,
:patient-id 222})
=>
({:deleted 0,
:drug-flag 1,
:drug-id 1,
:cost-date #object[java.time.LocalDate 0x2d30b554 "2019-05-07"],
:id "1",
:create-time #object[java.time.LocalDateTime 0x76211aed "2019-06-05T22:42:14"],
:count 2,
:drug-name "安脱达",
:patient-id "222",
:sum 58.0}
{:deleted 0,
:drug-flag 1,
:drug-id 1,
:cost-date #object[java.time.LocalDate 0x9e55443 "2019-06-05"],
:id "3",
:create-time #object[java.time.LocalDateTime 0x7114ec3c "2019-06-05T22:42:01"],
:count 10,
:drug-name "安脱达",
:patient-id "222",
:sum 120.0}
{:deleted 0,
:drug-flag 1,
:drug-id 4,
:cost-date #object[java.time.LocalDate 0x59267d5f "2019-05-07"],
:id "2",
:create-time #object[java.time.LocalDateTime 0x27aef2e4 "2019-06-05T22:41:50"],
:count 15,
:drug-name "奥马珠",
:patient-id "222",
:sum 200.0})
json以后格式是一条条的record:
"data": [
{
"deleted": 0,
"drug-flag": 1,
"drug-id": 1,
"cost-date": "2019-05-07",
"id": "1",
"create-time": "2019-06-05T22:42:14",
"count": 2,
"drug-name": "安脱达",
"patient-id": "222",
"sum": 58
},
{
"deleted": 0,
"drug-flag": 1,
"drug-id": 1,
"cost-date": "2019-06-05",
"id": "3",
"create-time": "2019-06-05T22:42:01",
"count": 10,
"drug-name": "安脱达",
"patient-id": "222",
"sum": 120
},
{
"deleted": 0,
"drug-flag": 1,
"drug-id": 4,
"cost-date": "2019-05-07",
"id": "2",
"create-time": "2019-06-05T22:41:50",
"count": 15,
"drug-name": "奥马珠",
"patient-id": "222",
"sum": 200
}
]
而预期的json是干这么几件事:
1、根据日期将分组,以指定字段为key,group的日期为value
2、对日期进行格式化
3、同一日期下的数据,以list为key,record作为value
4、对每个list里record的sum字段求和,与list同级,以total-cost为key,和为value
5、同4类似,对list里的record的count求和,与list同级,以total-count为key,和为value
{
"content": [
{
"cost-date": "2019-05-07",
"list": [
{
"deleted": 0,
"drug-flag": 1,
"drug-id": 1,
"cost-date": "2019-05-07",
"id": "1",
"create-time": "2019-06-05T22:42:14",
"count": 2,
"drug-name": "安脱达",
"patient-id": "222",
"sum": 58
},
{
"deleted": 0,
"drug-flag": 1,
"drug-id": 4,
"cost-date": "2019-05-07",
"id": "2",
"create-time": "2019-06-05T22:41:50",
"count": 15,
"drug-name": "奥马珠",
"patient-id": "222",
"sum": 200
}
],
"total-cost": 258,
"total-count": 17
},
{
"cost-date": "2019-06-05",
"list": [
{
"deleted": 0,
"drug-flag": 1,
"drug-id": 1,
"cost-date": "2019-06-05",
"id": "3",
"create-time": "2019-06-05T22:42:01",
"count": 10,
"drug-name": "安脱达",
"patient-id": "222",
"sum": 120
}
],
"total-cost": 120,
"total-count": 10
}
]
}
那么这个处理函数应该怎么写呢?
提供一个工具类,处理将关系数据库的record搞成tree的函数
(defn group-data-by-keys
"对一组数据库返回结果{data}进行处理, 使用{group-keys}中的key进行group-by:
(sut/group-data-by-keys test-dict
[:group-code1
:group-code2]
)
可以带多组额外的集合函数,多组[key reducing-function init-value]的格式:
(sut/group-data-by-keys test-dict
[:group-code]
:a
(fn [v e] (+ v (:id e)))
0
:b
(fn [v e] (+ v (:id e)))
0
)"
([data group-keys]
(->> data
(group-by (fn [m] (select-keys m group-keys)))
(reduce-kv (fn [m k v]
(assoc m k {:list
(mapv
(fn [e]
(apply dissoc e group-keys))
v)}))
{})
(mapv (fn [e] (apply merge e)))))
([data group-keys key r-func val & krvs]
(->> data
(group-by (fn [m] (select-keys m group-keys)))
(reduce-kv (fn [m k v]
(assoc m
k (if (empty? krvs)
{:list
(mapv
(fn [e]
(apply dissoc e group-keys))
v)
key (reduce r-func val v)}
(apply assoc {:list
(mapv
(fn [e]
(apply dissoc e group-keys))
v)
key (reduce r-func val v)}
(let [krvs-seq (partition 3 krvs)]
(mapcat (fn [krv]
(let [[key r-func val] krv]
[key (reduce r-func val v)]))
krvs-seq))))))
{})
(map (fn [e] (apply merge e))))))
再提供一个相反作用的函数
(defn list-from-group-by
"去除分组, 作用和group-data-by-key 相反:
一层嵌套: (list-from-group-by {:y 1 :a [{:b 2} {:b 3}]} ))) -> [{:b 2, :y 1} {:b 3, :y 1}]
双层嵌套: (mapcat sut/list-from-group-by
(sut/list-from-group-by {:y 1 :a [{:b [{:x 99}]} {:b [{:x 77}]}]} ))
->
[{:x 99, :y 1} {:x 77, :y 1}]
"
[m]
(reduce-kv (fn [r k v]
(if (vector? v)
(->> (apply conj r v)
(map #(merge % (dissoc m k))))
r))
[]
m))
2、一些有用的utils
(defn lower-case-keywrod
"把输入的字符串变成keywrokd \"ABC\" -> :abc "
[s]
(keyword (clojure.string/lower-case s)))
(defn parse-int
"string 转 int"
[s]
(Integer/parseInt (re-find #"\A-?\d+" s)))
(defn parse-double
"string 转 doule"
[s]
(Double/parseDouble (re-find #"\A-?\d+" s)))
3、筛选和判断一组数据中不为nil的
有这么一组数:
(def x '[(nil nil nil nil nil) (nil nil nil nil nil) ({:drug-id "300", :drug-name "西替利嗪,左西替利嗪(仙特朗,优泽)", :checked true, :dosage "1111", :dosage-unit "滴/天"} nil {:drug-id "302", :drug-name "谈说斯汀(UPDATE)", :checked true, :dosage "1111", :dosage-unit "滴/天"} nil) ()])
找出不为nil的
(filter (complement nil?) (mapcat identity x))
4、在数组中找出符合条件的元素
(first (filter (complement nil?)
[a b]))
(first (filter #(= % :a) [:a :b :c :d]))
some实现
(some #{:a} [:a :b :c :d])
因为set也是一个函数
- 如何快速返回,不用全部遍历呢?-------
在reduce中使用reduced 函数
如果我们想一旦求和的结果大于100,我们就返回:big,并且中断计算。
(reduce (fn [a v] (if (< a 100) (+ a v) (reduced :big))) (range 10))
返回值:45
(reduce (fn [a v] (if (< a 100) (+ a v) (reduced :big))) (range 20))
返回值::big
5、类似第一条,将json数据转成map,并做拼接处理。
需要实现的添加和详情页面效果如下,
add
需要后台在详情接口将数据拼接好:
UI
db中存储的是json,通过(db/get-reaction-detail {:id id})查找到的原始数据结构:
{
"id": "2",
"reaction": [
{
"list": [
{
"show": true,
"value-id": 53,
"parent-id": 52,
"group-code": "REACTION",
"dict-value-code": "SHOUBIZHONGZHANG",
"dict-value-name": "手臂肿胀",
"dict-value-sort": 1
},
{
"show": false,
"value-id": 54,
"parent-id": 52,
"group-code": "REACTION",
"dict-value-code": "RE",
"dict-value-name": "热",
"dict-value-sort": 2
},
{
"show": false,
"value-id": 55,
"parent-id": 52,
"group-code": "REACTION",
"dict-value-code": "TENTTONG",
"dict-value-name": "疼痛",
"dict-value-sort": 3
},
{
"show": true,
"value-id": 56,
"parent-id": 52,
"group-code": "REACTION",
"dict-value-code": "SAOYANG",
"dict-value-name": "瘙痒",
"dict-value-sort": 4
},
{
"show": false,
"value-id": 57,
"parent-id": 52,
"group-code": "REACTION",
"dict-value-code": "HUODONGSHOUXIAN",
"dict-value-name": "活动受限",
"dict-value-sort": 5
}
],
"dict-key-id": 52,
"dict-key-code": "JU-BU-FAN-YING",
"dict-key-name": "局部反应",
"dict-key-sort": 1
},
{
"list": [
{
"show": false,
"value-id": 59,
"parent-id": 58,
"group-code": "REACTION",
"dict-value-code": "FARE",
"dict-value-name": "发热",
"dict-value-sort": 1
},
{
"show": false,
"value-id": 60,
"parent-id": 58,
"group-code": "REACTION",
"dict-value-code": "PIJUAN",
"dict-value-name": "疲倦",
"dict-value-sort": 2
},
{
"show": true,
"value-id": 61,
"parent-id": 58,
"group-code": "REACTION",
"dict-value-code": "GUANJIETONG",
"dict-value-name": "关节痛",
"dict-value-sort": 3
}
],
"dict-key-id": 58,
"dict-key-code": "FEI-TE-YI-XING-FAN-YING",
"dict-key-name": "全身非特异性反应",
"dict-key-sort": 2
},
{
"list": [
{
"show": true,
"value-id": 63,
"parent-id": 62,
"group-code": "REACTION",
"dict-value-code": "CHUANXI",
"dict-value-name": "喘息",
"dict-value-sort": 1
},
{
"show": true,
"value-id": 64,
"parent-id": 62,
"group-code": "REACTION",
"dict-value-code": "KESOU",
"dict-value-name": "咳嗽",
"dict-value-sort": 2
},
{
"show": false,
"value-id": 65,
"parent-id": 62,
"group-code": "REACTION",
"dict-value-code": "XIONGMEN",
"dict-value-name": "胸闷",
"dict-value-sort": 3
},
{
"show": false,
"value-id": 66,
"parent-id": 62,
"group-code": "REACTION",
"dict-value-code": "QIBI",
"dict-value-name": "憋气",
"dict-value-sort": 4
},
{
"show": false,
"value-id": 67,
"parent-id": 62,
"group-code": "REACTION",
"dict-value-code": "YANYANGBUSHI",
"dict-value-name": "咽痒不适",
"dict-value-sort": 5
}
],
"dict-key-id": 62,
"dict-key-code": "XIAOCHUANZHENGZHUANG",
"dict-key-name": "哮喘症状",
"dict-key-sort": 3
},
{
"list": [
{
"show": false,
"value-id": 69,
"parent-id": 68,
"group-code": "REACTION",
"dict-value-code": "BIYANG",
"dict-value-name": "鼻痒",
"dict-value-sort": 1
},
{
"show": false,
"value-id": 70,
"parent-id": 68,
"group-code": "REACTION",
"dict-value-code": "PENGTI",
"dict-value-name": "喷嚏",
"dict-value-sort": 2
},
{
"show": false,
"value-id": 71,
"parent-id": 68,
"group-code": "REACTION",
"dict-value-code": "LIUTI",
"dict-value-name": "流涕",
"dict-value-sort": 4
},
{
"show": false,
"value-id": 72,
"parent-id": 68,
"group-code": "REACTION",
"dict-value-code": "BISAI",
"dict-value-name": "鼻塞",
"dict-value-sort": 5
},
{
"show": false,
"value-id": 73,
"parent-id": 68,
"group-code": "REACTION",
"dict-value-code": "BIGAN",
"dict-value-name": "鼻干",
"dict-value-sort": 6
}
],
"dict-key-id": 68,
"dict-key-code": "BI-YAN-ZHENG-ZHUANG",
"dict-key-name": "鼻炎症状",
"dict-key-sort": 4
},
{
"list": [
{
"show": false,
"value-id": 75,
"parent-id": 74,
"group-code": "REACTION",
"dict-value-code": "YANYANG",
"dict-value-name": "眼痒",
"dict-value-sort": 1
},
{
"show": false,
"value-id": 76,
"parent-id": 74,
"group-code": "REACTION",
"dict-value-code": "LIULEI",
"dict-value-name": "流泪",
"dict-value-sort": 2
},
{
"show": false,
"value-id": 77,
"parent-id": 74,
"group-code": "REACTION",
"dict-value-code": "JIEMOCHONGXUE",
"dict-value-name": "结膜充血",
"dict-value-sort": 3
},
{
"show": false,
"value-id": 78,
"parent-id": 74,
"group-code": "REACTION",
"dict-value-code": "WEIGUANG",
"dict-value-name": "畏光",
"dict-value-sort": 4
},
{
"show": false,
"value-id": 79,
"parent-id": 74,
"group-code": "REACTION",
"dict-value-code": "YANZHONG",
"dict-value-name": "眼肿",
"dict-value-sort": 5
}
],
"dict-key-id": 74,
"dict-key-code": "GUO-MIN-XING-JIE-MO-YAN",
"dict-key-name": "过敏性结膜炎症状",
"dict-key-sort": 5
},
]
}
处理函数:
(let [detail (db/get-reaction-detail {:id id})
reaction (j/read-json (:reaction detail))
selected-reac (transform [ALL :list] (fn [e]
(let [t (filter #(true? (:show %)) e)]
(string/join "/" (map :dict-value-name t)))
) reaction)]
(assoc detail :reaction selected-reac))
处理结果:
"reaction": [
{
"list": "手臂肿胀/热/瘙痒",
"dict-key-id": 52,
"dict-key-code": "JU-BU-FAN-YING",
"dict-key-name": "局部反应",
"dict-key-sort": 1
},
{
"list": "",
"dict-key-id": 58,
"dict-key-code": "FEI-TE-YI-XING-FAN-YING",
"dict-key-name": "全身非特异性反应",
"dict-key-sort": 2
},
{
"list": "喘息/咳嗽",
"dict-key-id": 62,
"dict-key-code": "XIAOCHUANZHENGZHUANG",
"dict-key-name": "哮喘症状",
"dict-key-sort": 3
},
{
"list": "",
"dict-key-id": 68,
"dict-key-code": "BI-YAN-ZHENG-ZHUANG",
"dict-key-name": "鼻炎症状",
"dict-key-sort": 4
},
{
"list": "",
"dict-key-id": 74,
"dict-key-code": "GUO-MIN-XING-JIE-MO-YAN",
"dict-key-name": "过敏性结膜炎症状",
"dict-key-sort": 5
},
{
"list": "血管性水肿",
"dict-key-id": 80,
"dict-key-code": "GUO-MIN-XING-PI-FU",
"dict-key-name": "过敏性皮肤症状",
"dict-key-sort": 6
}
]
网友评论