news 2026/9/7 20:11:22

D3.js d3-array 集运算详解:difference、union、intersection 与 superset、subset、disjoint 的完整用法

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
D3.js d3-array 集运算详解:difference、union、intersection 与 superset、subset、disjoint 的完整用法

D3.js d3-array 集运算详解:difference、union、intersection 与 superset、subset、disjoint 的完整用法

【免费下载链接】d3Bring data to life with SVG, Canvas and HTML. :bar_chart::chart_with_upwards_trend::tada:项目地址: https://gitcode.com/GitHub_Trending/d3/d3

本文基于 D3.js 官方文档中的 Set operations 一章,系统讲解 d3-array 提供的六个逻辑集运算函数——d3.difference(差集)、d3.union(并集)、d3.intersection(交集)、d3.superset(超集判断)、d3.subset(子集判断)和d3.disjoint(不相交判断)。读完本文,你将掌握这些函数的签名、返回值语义与取值顺序规则,理解其返回类型InternSet与普通Set的差异,并能在数据清洗、用户群差异分析等实际场景中直接用任意可迭代对象完成集合逻辑运算。

六个集运算函数总览

d3-array 将集合逻辑运算抽象为对"任意可迭代对象(any iterable)"操作的一组函数,这是该章节的原始定位:"Logical set operations for any iterable."。六个函数分为两类:

函数签名返回值用途
d3.differencedifference(*iterable*, ...*others*)InternSet差集:iterable中不在任何others里的值
d3.unionunion(...*iterables*)InternSet并集:所有iterables中出现的(去重后的)全部值
d3.intersectionintersection(...*iterables*)InternSet交集:在所有iterables中都出现的(去重后的)值
d3.supersetsuperset(*a*, *b*)booleana是否包含b的全部值(ab的超集)
d3.subsetsubset(*a*, *b*)booleana的每个值是否都在b中(ab的子集)
d3.disjointdisjoint(*a*, *b*)booleanab是否没有任何共享值

这组函数通过本仓库的 src/index.js 以export * from "d3-array"的形式整体重导出,因此在安装d3包后直接d3.union(...)等调用即可;从 package.json 可以看到,当前 d3 版本为 7.9.0,依赖d3-array: ^3.2.4,集运算函数属于该依赖包的 API 面。完整索引还可参考 docs/api.md 中 "Sets" 一节。

d3.difference:计算差集

d3.difference(*iterable*, ...*others*)接收一个基集iterable和任意数量的其他可迭代对象others,返回一个新的InternSet,其中包含iterable不存在于任何others的每一个值。

官方文档给出的示例:

d3.difference([0, 1, 2, 0], [1]) // Set {0, 2}

基集中虽然0出现了两次,但返回结果只保留一份;1因为在第二个参数[1]中出现而被剔除。

典型场景是"排除已处理的记录":给定一批全部用户 ID 和一个黑名单,d3.difference(allIds, blacklist)就是需要保留的用户集合。由于第二个及之后的参数是变参(...*others),也可以同时排除多个来源:

// 从候选集中排除 A、B 两个来源的值 const candidates = d3.difference([10, 20, 30, 40], [20], [40, 50]); // Set {10, 30}

d3.union:计算并集

d3.union(...*iterables*)对任意多个可迭代对象求并集,返回的InternSet包含在所有给定iterables中出现过的每一个去重后的值。一个关键规则是:结果集中值的顺序基于它们在给定iterables中首次出现的先后(order based on first occurrence)

官方文档示例:

d3.union([0, 2, 1, 0], [1, 3]) // Set {0, 2, 1, 3}

注意结果的顺序{0, 2, 1, 3}不是数值升序,而是按照0、2、1来自第一个数组的首次出现顺序,随后补上仅在第二个数组中首次出现的3。这意味着并集结果保留了原始数据的出现次序,而非排序后的次序,这在需要保持记录原始顺序(如时间序列中的事件 ID)时是有意义的。

// 合并多张表中的字段名,保持首次出现顺序 const fields = d3.union(["id", "name"], ["name", "email", "id"]); // Set {id, name, email}

d3.intersection:计算交集

d3.intersection(...*iterables*)返回一个InternSet,包含在所有给定iterables中都出现的每一个(去重后的)值;同样地,结果顺序基于首次出现顺序。

官方文档示例:

d3.intersection([0, 2, 1, 0], [1, 3]) // Set {1}

只有1同时出现在两个数组中,因此交集为{1}。交集常用于找出多个数据源的公共键,例如多张 CSV 记录共同的站点 ID:

const common = d3.intersection(sitesA, sitesB, sitesC); // 三张表都出现的站点

与并集不同,如果某个值只出现在部分输入中,它就会被排除;变参形式允许对两个以上集合求交。

superset、subset 与 disjoint:布尔判断

与前三者返回集合不同,剩余三个函数只做判断,返回布尔值:

  • d3.superset(*a*, *b*):当ab超集时返回true,即b中的每个值也都在a中。
d3.superset([0, 2, 1, 3, 0], [1, 3]) // true
  • d3.subset(*a*, *b*):当ab子集时返回true,即a中的每个值也都在b中。注意它与superset互为参数位置上的对偶:d3.subset(x, y)等价于d3.superset(y, x)
d3.subset([1, 3], [0, 2, 1, 3, 0]) // true
  • d3.disjoint(*a*, *b*):当ab不相交(disjoint)时返回true,即两个集合没有任何共享值。
d3.disjoint([1, 3], [2, 4]) // true

这三个判断函数接受的是"给定可迭代对象",内部按值相等性比较;disjoint尤其适合做"两个筛选条件是否互斥"的快速校验,而不必实际计算交集再检查是否为空。

返回值类型 InternSet:为何不是原生 Set

differenceunionintersection的返回值被文档明确标注为 InternSet,这是 d3 对原生Set的扩展(InternSet/InternMap分别继承自原生Set/Map),其核心能力是绕过 SameValueZero 相等性算法,允许以Date等非原始值(non-primitive values)作为集合元素。

原生Set使用同一引用或 SameValueZero 判定重复,而InternSet在判断相等时会对非原始值调用key函数,默认为object.valueOf。因此在 docs/d3-array/intern.md 中演示的按日期去重场景里,两个内容相同的Date对象会被视为"同一个值":

const dates = new d3.InternSet([ new Date("2022-01-01"), new Date("2022-01-01") // 视为同一个值,集合中仅保留一个 ]);

这直接影响集运算的正确性:如果你用原生Set对包含Date的对象数组求uniondifference,两个"值相同但引用不同"的日期会被当作两个元素;而 d3 的集运算函数统一返回InternSet,恰好规避了这个问题。文档同时指出d3.groupd3.rollupd3.index内部也是用InternMap而非原生Map,即 d3 在"按值分组/集合化"这条主线上对非原始值是一致地做了内省化(interning)处理。

实战:在数据管道中做差异分析与覆盖校验

结合上述函数,一个常见的数据管道片段是:从数据源 A 中筛出"新增项"、校验"配置覆盖"、并检查"两组 ID 是否冲突"。由于输入可以是任意可迭代对象(数组、Set、迭代器均可),这些运算可以无缝嵌入已有的 d3 数据处理流:

import * as d3 from "d3"; const lastWeek = [101, 102, 103]; const thisWeek = [102, 103, 104]; // 本周新增的用户(差集) const newUsers = d3.difference(thisWeek, lastWeek); // Set {104} // 本周流失的用户(反方向差集) const lostUsers = d3.difference(lastWeek, thisWeek); // Set {101} // 持续存在的用户(交集) const retained = d3.intersection(thisWeek, lastWeek); // Set {102, 103} // 校验:本周名单是否为上周名单的超集(是否有用户流失) const noLoss = d3.superset(thisWeek, lastWeek); // false // 校验:两个渠道的 ID 是否完全互斥(无重复投放) const exclusive = d3.disjoint(channelA, channelB); // true / false

上面的语义均可由本文列出的官方示例直接推出:d3.difference([0, 1, 2, 0], [1])得到Set {0, 2}d3.superset([0, 2, 1, 3, 0], [1, 3])得到true等。使用时的两点注意:一是结果顺序遵循"首次出现顺序"而非排序,需要有序输出时请自行d3.sort([...set]);二是这些函数只按值的内省化相等性比较,对NaN等特殊值以及对象结构(嵌套对象不会被深度比较)的处理仍取决于valueOf的默认行为,若需自定义相等规则,应转向带key函数的 InternSet 构造方式自行组织集合。

环境说明与延伸阅读

  • 适用前提:安装 d3 7.x(本仓库为 7.9.0)及其依赖d3-array ^3.2.4后,六个函数即可通过全局d3命名空间调用;仓库入口 src/index.js 逐模块export *,因此也适合按模块按需引入d3-array
  • 本文所有函数签名与示例均取自 docs/d3-array/sets.md,返回类型与相等性规则参见 docs/d3-array/intern.md,d3-array 各主题入口见 docs/d3-array.md。
  • 各函数在上游 d3-array 包中的源码位置(difference.jsunion.jsintersection.jssuperset.jssubset.jsdisjoint.js)由官方文档给出,可对照上游仓库验证实现细节。

【免费下载链接】d3Bring data to life with SVG, Canvas and HTML. :bar_chart::chart_with_upwards_trend::tada:项目地址: https://gitcode.com/GitHub_Trending/d3/d3

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/7 20:10:11

大数据深度学习|计算机毕设项目|计算机毕设答辩|flask基于人工智能的智能客服系统的设计与实现

标题:flask基于人工智能的智能客服系统的设计与实现文档介绍:第一章 概述1.1研究背景和意义随着互联网技术的飞速发展和普及,越来越多的企业开始提供在线服务,客户服务作为企业与客户沟通的重要桥梁,其质量和效率直接影…

作者头像 李华
网站建设 2026/9/7 20:08:35

SQLite Insert 全面解析:语法、UPSERT、批量优化与避坑指南

刚接触 SQLite 的时候,很多人的第一反应是“这不就是个嵌入式数据库嘛,Insert 还能玩出花来?”说实话,我一开始也是这么想的。直到后来我在一个数据迁移项目里连续踩了几天坑,才发现自己连最基础的 INSERT INTO 都没吃…

作者头像 李华
网站建设 2026/9/7 20:07:12

装备制造企业AI+智能工厂解决方案【附全文阅读】

本 42 页 PPT 面向装备制造行业,是智能工厂咨询项目投标、方案宣讲的实战素材。文档深度剖析装备制造定制化订单多、BOM 复杂、生产周期长、多系统数据孤岛、AI 落地缺少行业数据集等典型痛点。搭建分层技术架构,覆盖数据采集、生产执行到智能决策全层级…

作者头像 李华
网站建设 2026/9/7 20:06:51

Django+微信小程序校园店铺商城开发实战:从架构到部署

1. 项目整体设计与技术选型思路1.1 校园店铺商城到底在解决什么问题校园电商和外面的大电商看起来都是“买卖”,实际做起来完全是两码事。学生群体高度集中,消费场景天然带周期性和潮汐性:饭点下单奶茶、晚上买夜宵、开学季买二手教材、毕业季…

作者头像 李华