假设我有一个字符串集合,我希望返回超过4个字符的所有字符串,首先按最短字符串排序。
你可以通过以下方式解决这个问题:
(def strings ["this" "is" "super" "cool" "everybody" "isn't" "clojure" "great!?!?"])
(sort-by count < (filter #(> (count %) 4) strings))
;; > ("super" "isn't" "clojure" "everybody" "great!?!?")
请注意,我们两次使用count
。这可能在这里很好,但如果count
不是count
怎么办?如果我们调用count
而不是super-expensive-function
而不是绝对必要的话,那么我们真的不会运行超过{{1}}而不是什么呢?
所以:
是否存在执行此功能的现有功能,还是需要构建自己的功能?
答案 0 :(得分:8)
最简单的解决方案是将每个项目与其昂贵的计算属性配对,然后过滤和排序,然后丢弃参数:
(->> strings
(map (juxt identity count))
(filter (fn [[_ c]] (> c 4)))
(sort-by peek)
(map first))
如果计算有问题的属性确实非常昂贵,那么分配向量的开销几乎会消失。
答案 1 :(得分:1)
也许JIT编译器可以发现这个昂贵的中间结果可以在两个操作之间缓存?鉴于手动缓存结果的复杂性增加,值得尝试排除这种可能性。对于各种时间测量解决方案,我会进行几次性能测试:
(time (dotimes [_ 1e5] ...))
答案 2 :(得分:0)
您可以使用group-by进行配对,并使用列表推导进行聚合和过滤。
(for [[c sv] (sort-by first (group-by count strings)) :when (> c 4) s sv] s)