You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Clojure:如何将集合的分区规则映射到同大小的另一集合

按已有分区规则对另一集合分区的优雅实现

我有两个大小相同的集合,已经对第一个集合完成了分区,希望把相同的分区规则应用到第二个集合。自己写了个实现,但看起来不够简洁:

(def x (range 50 70))
(def y [(range 5) (range 10) (range 3) (range 2)]) ; 我的分区方案,对应20个元素

(drop-last
  (reduce (fn [a b] (concat (drop-last a)
                            (split-at (count b) (last a))))
          [x] y))

更优雅的实现方式

核心思路是先提取已有分区的长度列表,再用这些长度对目标集合做分段切割,下面是两种简洁高效的写法:

方法1:利用累加分割点(适用于向量,效率最高)

(let [lengths (map count y)
      ;; 生成分割索引:[0,5,15,18,20]
      split-points (reductions + 0 lengths)]
  (map (fn [start end] (subvec x start end)) split-points (rest split-points)))

方法2:通用序列版(兼容所有序列类型)

如果目标集合x不是向量,用take和drop组合更通用:

(let [lengths (map count y)
      split-points (reductions + 0 lengths)]
  (map (fn [start end] (take (- end start) (drop start x))) split-points (rest split-points)))

封装成可复用函数

如果需要多次使用,可以封装成函数:

(defn apply-partition [target-col source-partitions]
  (let [lengths (map count source-partitions)
        split-points (reductions + 0 lengths)]
    (map (fn [s e] (take (- e s) (drop s target-col))) split-points (rest split-points))))

;; 调用示例
(apply-partition x y)

为什么原实现不够理想

原代码每次reduce都要做concat和split-at,频繁创建中间序列,当集合较大时效率会明显下降。而上面的方法先一次性计算好所有分割位置,再批量生成分区,逻辑更清晰,性能也更优。

内容的提问来源于stack exchange,提问作者alex314159

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 19:07:36