d3-collection

几种常用的键值对类型的数据结构

Installing

NPM 安装:npm install d3-collection, 还可以下载最新版,此外还可以直接从 d3js.org单独的标准库 或作为 D3 4.0 的一部分引入,支持 AMD, CommonJS 以及 vanilla 环境, 使用标签引入会暴露 d3 全局变量:

<script src="https://d3js.org/d3-collection.v1.min.js"></script>
<script>

var map = d3.map()
    .set("foo", 1)
    .set("bar", 2);

</script>

在浏览器中测试 d3-collection

API Reference

Objects

在JavaScript中常见的数据类型是 associative array(关联数组), 简言之就是具有一个属性集的 对象. 对象的的标准迭代方式是 for…in 循环, 但是迭代次序是未定义的. D3 提供了几种将对象转为数字索引的标准数组的方法.

请注意:当使用普通对象作为属性名是可以的,但是当使用特殊内置的属性名时会导致意想不到的事发生,比如使用 object["__proto__"] = 42"hasOwnProperty" in object. 如果不能保证映射的键是安全的情况下请使用 mapssets(或标准的ES6数据结构)来代替对象.

# d3.keys(object) <源码>

返回一个包含了指定对象属性名的数组. 数组的顺序是未定义(不可靠)的.

# d3.values(object) <源码>

返回一个包含了指定对象属性值的数组. 数组的顺序是未定义(不可靠)的.

# d3.entries(object) <源码>

将对象转为标准的包含 keyvalue 的对象数组.也就是将对象的 key-value 对重组为一个对象, 比如将 {foo: 42} 转为 {key: "foo", value: 42}. 所传入的对象被重组为一个数组. 次序同样是不固定的:

d3.entries({foo: 42, bar: true}); // [{key: "foo", value: 42}, {key: "bar", value: true}]

Maps

ES6 Maps 类似, 但是有以下几点不同:

# d3.map([object[, key]]) <源码>

构建一个新的 map. 如果指定了 object 则将其所有的可枚举对象复制到 map 中. object 可以是一个数组也可以是其他的 map 对象.可选的 key 方法用来指定使用哪个属性作为key, 比如:

var map = d3.map([{name: "foo"}, {name: "bar"}], function(d) { return d.name; });
map.get("foo"); // {"name": "foo"}
map.get("bar"); // {"name": "bar"}
map.get("baz"); // undefined

参考 nests.

# map.has(key) <源码>

当且仅当 map 中包含指定的 key 的时候返回 true, 要注意其对应的 value 可能为 null 或者 undefined

# map.get(key) <源码>

返回指定的 key 对应的值,如果 map 中不包含指定的 key 则返回 undefined

# map.set(key, value) <源码>

设置 map 中指定的 keyvalue, 如果已经有相同的 key 字符串则会被覆盖,此方法返回 map 对象因此可以链式调用. 例如:

var map = d3.map()
    .set("foo", 1)
    .set("bar", 2)
    .set("baz", 3);

map.get("foo"); // 1

# map.remove(key) <源码>

如果 map 中包含指定的 key 则将其删除并返回 true, 否则什么都不做并返回 false.

# map.clear() <源码>

清空 map 中所有的项

# map.keys() <源码>

以数组的形式返回 map 中所有的 keys, 顺序是不可靠的.

# map.values() <源码>

以数组的形式返回 map 中所有的 value, 顺序是不可靠的.

# map.entries() <源码>

map 中所有的项重组为 key-value 数组. 顺序是随意的.每一项中 key 必须是字符串, 但是对应的 value 可以是任意的类型.

# map.each(function) <源码>

遍历 map 中的每一项, 并对每一项执行 function, 当前项的 valuekey 作为参数, 随后是 map 本身, 返回 undefined.

# map.empty() <源码>

当且仅当 map 中没有任何项时返回 true.

# map.size() <源码>

返回 map 中项的个数.

Sets

ES6 Sets类似,但是有以下不同:

# d3.set([array[, accessor]]) <源码>

构建一个新的 set 对象. 如果指定了 array 则将 array 中的元素都作为 set 的元素并返回.array 也可以是其他的 set 对象.如果指定了 accessor , 则在将元素添加到 set 之前先对每个元素执行执行的访问器方法.

# set.has(value) <源码>

set 中包含指定的 value 字符串时返回 true.

# set.add(value) <源码>

将指定的 value 字符串添加到 set 中并返回 set, 因此支持链式语法:

var set = d3.set()
    .add("foo")
    .add("bar")
    .add("baz");

set.has("foo"); // true

# set.remove(value) <源码>

如果 set 中存在 value 字符串则将其移除并返回 true, 否则什么都不做并返回 false.

# set.clear() <源码>

清空 set.

# set.values() <源码>

以数组的形式返回 set 中所有的 values, 顺序是任意不可信的,可以方便的用来去重:

d3.set(["foo", "bar", "foo", "baz"]).values(); // "foo", "bar", "baz"

# set.each(function) <源码>

set 中每个元素执行 function, 前两个参数都为 value(为了和 map.each对称),其次为 set 自身. 最终返回 undefined, 遍历次序任意不可信.

# set.empty() <源码>

set 中没有任何项时返回 true.

# set.size() <源码>

返回 set 中包含的项的个数.

Nests

Nests(嵌套操作)可以将数组类型的元素重组为层次结构数据。想象一下 SQL 中的 GROUP BY 操作。除了可以对元素进行分组之外,嵌套操作的输出是一个树而不是扁平的表。树的具体结构层级由 key 函数决定。同时可以根据 value 对树的叶节点进行排序,而非叶节点可以根据 key 进行排序. 可选的 rollup 操作可以用来指定对叶节点组进行处理的函数。Nest 操作(由nest返回的对象)是可以多次使用的,并且不保留对嵌套数据的任何引用。

例如,考虑如下的扁平数据结构:

var yields = [
  {yield: 27.00, variety: "Manchuria", year: 1931, site: "University Farm"},
  {yield: 48.87, variety: "Manchuria", year: 1931, site: "Waseca"},
  {yield: 27.43, variety: "Manchuria", year: 1931, site: "Morris"},
  ...
];

在可视化时可能需要先根据年份然后按照类别进行分组重构,可以进行如下操作:

var entries = d3.nest()
    .key(function(d) { return d.year; })
    .key(function(d) { return d.variety; })
    .entries(yields);

返回的结果是一个嵌套的数组,最外层数据都由键值对组成:

[{key: "1931", values: [
   {key: "Manchuria", values: [
     {yield: 27.00, variety: "Manchuria", year: 1931, site: "University Farm"},
     {yield: 48.87, variety: "Manchuria", year: 1931, site: "Waseca"},
     {yield: 27.43, variety: "Manchuria", year: 1931, site: "Morris"}, ...]},
   {key: "Glabron", values: [
     {yield: 43.07, variety: "Glabron", year: 1931, site: "University Farm"},
     {yield: 55.20, variety: "Glabron", year: 1931, site: "Waseca"}, ...]}, ...]},
 {key: "1932", values: ...}]

嵌套的数据结构能轻松的在 SVGHTML 文档中生成分层结构。

更多介绍参考:

# d3.nest() <源码>

构建一个新的嵌套操作。keys 初始为空

# nest.key(key) <源码>

注册一个新的 key 函数,key 函数将会在输入数组的每个元素上进行调用,并且返回一个字符串标识用来对所有元素进行分组。大多数情况下,是一个简单的访问器,就行上述例子中的年份和种类访问器一样。(key 方法并不传递当前数组的索引),每次注册 key 后,其会被添加到 keys 内部数组的末尾,并且嵌套操作会根据指定的 key 再嵌套一层分组,某种意义上讲 key 的数量决定了最终嵌套结果的深度。

# nest.sortKeys(comparator) <源码>

current key(当前 key) 指定一个 comparator 函数用以对当前 key 下的元素排序。和 d3.ascendingd3.descending 类似。如果没有指定,则默认的 key 排序为 undefined。例如,在第一层和第二次分别根据 yearvarieties 进行排序:

var entries = d3.nest()
    .key(function(d) { return d.year; }).sortKeys(d3.ascending)
    .key(function(d) { return d.variety; }).sortKeys(d3.descending)
    .entries(yields);

排序操作仅仅影响 nest.entries 的结果。因为 nest.mapnest.object 返回的 keys 的顺序总是是未知的。

# nest.sortValues(comparator) <源码>

为嵌套操作的叶节点指定一个 comparator,和 d3.ascendingd3.descending 类似。这与对数组进行嵌套重组之前进行排序是大致一致的。如果没有指定比较函数,则元素的顺序会依照输入数组的顺序排序。这个操作对 nest.map, nest.entriesnest.object 都有影响。

# nest.rollup(function) <源码>

指定一个 rollup(归纳) 函数,应用在每个分组的叶节点上。归纳函数的返回值将代替由 nest.mapnest.object 返回的叶节点元素。对于nest.entries 操作,它会代替用 entry.value 代替 entry.values。如果指定了 leaf comparator 则叶节会在调用归纳函数之前调用。函数参数会传递当前叶节点组。注意:上述操作都在定义嵌套的行为,要将嵌套应用到具体的数据上,需要调用 nest.map, nest.object 或者 nest.entries 方法来获取嵌套后的具体形式

# nest.map(array) <源码>

将嵌套操作应用到指定的数组,并返回嵌套后的 [map](#map)。返回的 map 映射中的每一项都对应由第一个 key 函数的返回的独特的 key 值。每一项的值都取决于注册的 key 函数的数量:如果不止一个 key 函数则值是一个 map,否则就是数组中经过过滤之后对应的 key 的元素数组。如果没有定义 key 函数,则返回输入数组。

# nest.object(array) <源码>

将指定的嵌套操作应用到指定的 array, 返回一个嵌套对象。返回的关联数组中的每一项都与第一个 key 函数相关。每一项的值取决于 key 函数的个数:如果不止一个 key 函数则值为一个关联数组,否则是经过 key 函数过滤之后的数组。

注意的是如果输入数组中包括与 JavaScript 内置 key(比如__proto__)冲突的话是不安全的。如果不能保证数组中所有的 key 都是安全的请使用 nest.map 代替。

# nest.entries(array) <源码>

将指定的嵌套操作应用到指定的 array,返回经过嵌套处理后的 key-values 对。与将 map.entries 应用到关联数组类似。但是具有层次结构,嵌套体现在 value,如果指定了多个 key 则如果对应的 key 下有数据的话,其 value 也为一个 key-values 对象,以此类推。

最后更新: 2019-5-18 18:11:02
本站功能逐步完善中,如果您对本站有好的建议或者意见,欢迎留言。 取 消 确 定