ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

TIL:在 Clojure 中用 clojure.math.combinatorics 从序列生成组合

TIL:在 Clojure 中用 clojure.math.combinatorics 从序列生成组合 文档教程知识库【免费下载链接】til:memo: Today I Learned项目地址https://gitcode.com/gh_mirrors/ti/til点击查看免费下载本篇 TIL 笔记源自 clojure/combinations-of-items-from-a-sequence.md讲解如何在 Clojure 中借助clojure.math.combinatorics库的combinations函数从一个序列中枚举出所有指定大小的组合。读完本文你将掌握组合与排列的区别、combinations的完整用法与返回结构、如何验证组合总数C(n, k)以及在大输入下的惰性处理技巧可直接迁移到分组配对、测试用例生成等实战场景。场景从 5 个人中唯一配对 2 人有时我们想从一个列表中取出所有组合。例如有 5 个人希望知道从这 5 人中唯一配对出 2 人的全部方式——这正是组合数学中的从 5 个元素中取 2 个的组合问题记作 C(5, 2)其结果为C(5, 2) 5! / (2! × (5-2)!) 1010 种配对方式里(A, B)与(B, A)被视为同一种组合因为组合不关心元素的排列顺序——这正是它区别于排列permutation的核心。若你恰好需要顺序有意义的排列可以对比仓库中的另一篇笔记 math/generate-permutations-of-all-valid-9-ball-racks.md那篇以 9 球开球排列为例介绍了用Array#permutation枚举 7! 5040 种排列的思路。引入 math.combinatorics 库Clojure 官方组织的 clojure/math.combinatorics 中的 Clojure 分类索引因此在任意 Clojure 项目中按以下方式引入即可Leiningen在project.clj的:dependencies中添加[org.clojure/math.combinatorics 0.2.0]tools.deps在deps.edn的:deps中添加org.clojure/math.combinatorics {:mvn/version 0.2.0}以上坐标以当前公开发布的版本为准实际使用时可替换为项目锁定的最新版本号。引入后在 REPL 中加载命名空间即可使用。原笔记中使用的是use形式(use [clojure.math.combinatorics :as combo])在现代 Clojure 代码中更推荐使用require语义更清晰且不会污染当前命名空间(require [clojure.math.combinatorics :as combo])如果不记得库中到底提供了哪些函数可以参考仓库笔记 clojure/list-functions-for-a-namespace.md 中的方法用(dir clojure.math.combinatorics)或(keys (ns-publics clojure.math.combinatorics))列出全部公开函数。combinations 的用法与完整示例combinations函数接收两个参数一个元素集合列表/向量/集合等序列以及一个整数表示每个组合的大小。原笔记给出的示例是从 5 位角色名中两两配对(use [clojure.math.combinatorics :as combo]) (combo/combinations [Liz, Tracy, Kenneth, Jack, Jenna] 2) ; ((Liz Tracy) (Liz Kenneth) (Liz Jack) ; (Liz Jenna) (Tracy Kenneth) (Tracy Jack) ; (Tracy Jenna) (Kenneth Jack) (Kenneth Jenna) ; (Jack Jenna))观察输出可以验证两点组合数正确5 个元素取 2 个共 10 种组合输出恰好 10 个元素与 C(5, 2) 10 一致无重复、无遗漏。顺序有规律组合按输入序列的顺序以字典序生成——以Liz打头的组合排在最前然后是Tracy、Kenneth、Jack依次打头。这使结果可预测便于调试与断言。函数行为参数语义与惰性序列从combinations的签名与行为可以推断其核心语义第一个参数任意可遍历的集合vector、list、set 均可。示例中使用的是字符串向量。第二个参数组合大小k即每个结果分组中元素的个数。返回值一个序列其每个元素都是一个大小为 k 的组合以有序集合形式呈现。由于组合枚举可以按索引递增的方式逐步产出该序列是以惰性lazy方式生成的——这意味着面对大集合时我们不需要一次性物化全部结果可以按需取出前几个。配合 Clojure 的take即可实现只枚举前 N 个组合的按需消费模式(take 3 (combo/combinations (range 1 11) 3)) ; ((1 2 3) (1 2 4) (1 2 5))边界情况与实用建议组合是组合爆炸combinatorial explosion的高发地带使用时需注意以下边界场景行为说明k 0返回一个仅含空组合的序列(())即什么都不选这一种方式k 1返回与输入元素一一对应的单元素组合共 n 个k n元素数量不足无法构成任何大小为 k 的组合结果为空的惰性序列大集合大 kC(n, k) 增长迅速如 C(100, 50) 数量级极大务必配合take或count评估后再全量消费实战扩展让组合落到业务代码中combinations不仅适用于字符串列表也适用于任何 Clojure 数据。几个典型用法1. 锦标赛对阵表——把队员两两配对生成全部对阵(combo/combinations [:alice :bob :carol :dave] 2) ; ((:alice :bob) (:alice :carol) (:alice :dave) ; (:bob :carol) (:bob :dave) (:carol :dave))2. 测试用例组合——枚举多个配置项的取值组合进行矩阵测试(def envs [staging production]) (def browsers [chrome firefox]) (combo/combinations envs 1) ; 单元素组合 (combo/combinations browsers 2) ; 双元素组合3. 与序列式处理函数组合——由于返回的是普通惰性序列可以无缝接入map、filter、reduce等 Clojure 核心函数。关于惰性序列的中间态构建可参考仓库笔记 clojure/reductions.md 了解reductions如何以惰性方式累积中间结果。小结clojure.math.combinatorics的combinations函数让从序列中枚举全部大小为 k 的组合变成一行代码传入集合与组合大小即可拿到按字典序生成、无重复的完整组合序列。理解其组合不关心顺序的语义、惰性生成的行为以及 C(n, k) 的增长规律就能在配对、抽样、测试矩阵等场景中安全高效地使用它。赞分享文档教程知识库【免费下载链接】til:memo: Today I Learned项目地址https://gitcode.com/gh_mirrors/ti/til点击查看免费下载相关推荐TIL在 Clojure REPL 中快速加载文件——load-file 用法与实践TIL在 Clojure REPL 中快速加载文件——load file 用法与实践 本篇技术指南以本仓库的 clojure/load a file into文档教程知识库TIL 笔记用 Clojure merge-with 将多个 Map 聚合为一个计数求和与列表拼接TIL 笔记用 Clojure merge with 将多个 Map 聚合为一个计数求和与列表拼接 merge with 是 Clojure 核心库中用于文档教程知识库LeetCode组合数学排列组合与生成函数在算法中的终极应用指南LeetCode组合数学排列组合与生成函数在算法中的终极应用指南 想要在LeetCode编程面试中脱颖而出组合数学是算法竞赛和面试中的核心利器LeetCo文档教程知识库创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表