Clojure嵌套向量处理:计算单价并升序排序优化咨询
优化Datomic查询结果的单价计算与排序实现
我从Datomic查询得到包含供应商名称、商品数量、订单状态、总价的嵌套向量,已经实现了计算单价并按单价升序排序的功能,想知道有没有更简洁高效的写法。
查询代码
(def order-info-query (->> (d/q '[:find ?si ?ia ?os ?p :where [?e :proposal/id _] [?e :proposal/supplier-id ?s] [?e :proposal/item-amount ?ia] [?e :proposal/amount ?p] [?e :proposal/order-status ?ps] [?s :company/brand-name ?si] [?ps :db/ident ?os] ] db) ) )
查询输出示例
(identity order-info-query) ;=> ;[["IBM" 10 :order-status/ongoing 110000] ; ["apple" 20 :order-status/waiting 239000] ; ["HP" 10 :order-status/ongoing 119000]]
现有实现代码
(sort-by last (mapv (fn [x] (let [[n c v b] x] (conj [] n c v b "Unit price:" (/ b c)))) order-info-query)) ;=> ;(["IBM" 10 :order-status/ongoing 110000 "Unit price:" 11000] ; ["HP" 10 :order-status/ongoing 119000 "Unit price:" 11900] ; ["apple" 20 :order-status/waiting 239000 "Unit price:" 11950])
优化方案
1. 简化映射逻辑(最直观的精简)
直接在函数参数里解构向量,去掉冗余的let和conj [],改用向量字面量构造结果,代码更简洁易读:
(sort-by last (map (fn [[name count status total]] [name count status total "Unit price:" (/ total count)]) order-info-query))
如果需要返回向量而非序列,保留mapv即可:
(sort-by last (mapv (fn [[name count status total]] [name count status total "Unit price:" (/ total count)]) order-info-query))
2. 用Transducer提升性能(大数据量场景)
如果处理的订单数据量较大,使用transducer可以避免创建中间集合,减少内存开销、提升效率:
(into [] (comp (map (fn [[n c s t]] [n c s t "Unit price:" (/ t c)])) (sort-by last)) order-info-query)
Transducer会把映射和排序操作合并执行,无需生成中间序列,适合处理大规模数据集。
3. 提前预计算排序键(避免重复计算)
sort-by默认会对每个元素多次计算排序键,若数据量较大,可先把单价和原数据绑定为map结构,再排序,确保排序键只计算一次,同时提升后续处理的灵活性:
(sort-by :unit-price (map (fn [[name count status total]] {:name name, :count count, :status status, :total total, :unit-price (/ total count)}) order-info-query))
内容的提问来源于stack exchange,提问作者Barış Can Ateş
相关产品推荐
相关产品推荐

