Wiki ▸ API Reference ▸ Core ▸ Arrays

当你使用D3处理数据可视化时,通常会倾向于做大量的数组操作。那是因为数组是D3的标准的数据呈现形式。数组处理的一些常见形式包括:取数组的一个连续片段(子集),使用判定函数过滤数组,使用变换函数映射数组为一组平行的值。在看到D3框架提供的一系列方法处理数组时,你应当很熟悉强大的JavaScript内置的数组的方法 JavaScript包含修改数组的赋值方法: • array.pop - 删除数组最后一位元素。 • array.push - 往数组的末尾新增一个或多个元素。 • array.reverse - 把数组元素的逆转顺序。 • array.shift - 删除数组第一位元素。 • array.sort - 给数组排序。 • array.splice - 给数组添加或者删除元素。 • array.unshift - 往数组的第一位新增一个或多个元素。 还有一些数组的存取方法,返回数组的一些描述: • array.concat - 合并数组或合并数组的值。 • array.join - 合并数组所有元素拼接成字符串。 • array.slice – 提取数组的一个选择。 • array.indexOf - 定位到数组第一个值。 • array.lastIndexOf - 定位到数组内最后一个值。 最后,对数组中的元素使用用函数的迭代方法: • array.filter – 由断言是true的元素创建一个新的数组。 • array.forEach –为数组中所有元素调用一个函数。 • array.every – 查看数组中是否每一项都满足某一条件。 • array.map – 用数组中的每个元素的函数返回结果创建一个新的数组。 • array.some -查看数组中是否有一项都满足某一条件。 • array.reduce -用函将数组减少为单一的值(从左至右). • array.reduceRight -用函将数组减少为单一的值(从右至左). 排序

d3.ascending(a, b)

如果a < b返回-1,a > b返回1,a=b返回0。 这是固有的比较器方法,也可用于关联内置数组排序的方法来给元素升序排序: function(a, b) { return a < b ? -1 : a > b ? 1 : 0; }

注意,如果没有给数组的内置排序方法没有指定比较器函数,那默认的排序是字典排序(按字母顺序排序),而非自然排列!所以当以数组的数字来排序时会导致bug。

d3.descending(a, b)

如果a >b返回-1,a < b返回1,a=b返回0。 这是固有的比较器方法,也可用于关联内置数组排序的方法来给元素降序排序: function(a, b) { return b < a ? -1 : b > a ? 1 : 0; }

注意,如果没有给数组的内置排序方法没有指定比较器函数,那默认的排序是字典排序(按字母顺序排序),而非自然排列!所以当以数组的数字来排序时会导致bug。

d3.min(array[, accessor])

返回给定数组(array)中自然排序最小的值。如果数组为空,返回undefined。如果指定了accessor 参数,等同与在计算最小值之前调用了array.map(accessor)方法。不同于内置的Math.min,这个方法会忽略未定义的值;这对比例尺定义域计算很有用处,当只考虑数据的定义区域。另外,元素的比较用的是自然排序而不是数字排序。例如,["20","3"]的最小值是20,然而[20,3]的最小值是3。

d3.max(array[, accessor])

返回给定数组(array)中自然排序最大的值。如果数组为空,返回undefined。如果指定了accessor 参数,等同与在计算最大值之前调用了array.map(accessor)方法。而并非内置的Math.max,这个方法会忽略未定义的值;这对当只需要定义数据的区域的比例尺定义域计算很有用处。另外,元素的比较用的是自然排序而不是数字排序。例如,["20","3"]的最大值是3,然而[20,3]的最大值是20。

d3.extent(array[, accessor])

返回给定数组(array)自然排序的最小值和最大值,等同于同时调用d3.min 和d3.max.

d3.sum(array[, accessor])

返回给定数组(array)的和。如果数组为空,返回 0。可选参数accessor 被指定,等同于在计算和之前调用array.map(accessor) 。此方法忽略无效值(如NaN 和undefined),当只考虑明确定义的值时这个方法计算数据和是很有用的。

d3.mean(array[, accessor])

返回给定数组(array)的平均数。如果数组为空,返回 undefined。可选参数accessor 被指定,等同在计算平均数之前调用array.map(accessor) 。此方法忽略无效值(如NaN 和undefined),当只考虑明确定义的值时这个方法计算数据和是很有用的。

d3.median(array[, accessor])

返回给定数组(array)以R-7算法得出的中位数。如果数组为空,返回 undefined。可选参数accessor 被指定,等同在计算中位数之前调用array.map(accessor) 。此方法忽略无效值(如NaN 和undefined) ,当只考虑明确定义的值时这个方法计算数据和是很有用的。

d3.quantile(numbers, p)

返回给定数组numbers的p分位数,其中p 是一个0到1范围的数。例如,中位数可以由p = 0.5计算,第一个四分位数是p = 0.25,第三个四分位数是p = 0.75。这个特别实现了R-7 运算法则,这是R编程语言和Excel默认的方式。这个方法需要数组numbers包含数字且数字升序顺序排列,例如使用 d3.ascending排序。 var a = [0, 1, 3]; d3.quantile(a, 0); // return 0 d3.quantile(a, 0.5); // return 1 d3.quantile(a, 1); // return 3 d3.quantile(a, 0.25); // return 0.5 d3.quantile(a, 0.75); // return 2 d3.quantile(a, 0.1); // return 0.19999999999999996

d3.bisectLeft(array, x[, lo[, hi]])

定位数组array 中的x的插入点,以保持已有序列。参数lo 和 hi 用来指定数组的子集;默认情况下整个数组都被使用。如果x在array中已存在,插入点在所有元素之前(左侧)。返回值是适合用作拼接已经排序数组array 的第一个参数。返回的插入点i把array 分为两个区:数组中所有array.slice(lo, i)中v < x 的v在左边,数组中所有 array.slice(i, hi)中v >= x 的v在右边。

d3.bisect(array, x[, lo[, hi]])

d3.bisectRight(array, x[, lo[, hi]])

和bisectLeft类似,但返回插入点来自于数组中任意实体之后(右侧)。返回的插入点i把array 分为两个区:数组中所有array.slice(lo, i)中v <= x的v在左边,数组中所有 array.slice(i, hi)中v > x 的v在右边。

d3.bisector(accessor)

d3.bisector(comparator)

Returns a bisector using the specified accessor or comparator function. The returned object has left and right properties which are similar to bisectLeft and bisectRight, respectively. This method can be used to bisect arrays of objects instead of being limited to simple arrays of primitives. For example, given the following array of objects: var data = [ {date: new Date(2011, 1, 1), value: 0.5}, {date: new Date(2011, 2, 1), value: 0.6}, {date: new Date(2011, 3, 1), value: 0.7}, {date: new Date(2011, 4, 1), value: 0.8} ]; 使用指定参数accessor或者comparator 函数返回一个二等分线。返回的对象有left 和right 属性,分别类似于bisectLeft和bisectRight方法。这个方法能用于二等分对象数组而不适用于原始的简单数组。例如下列对象的数组 var data = [ {date: new Date(2011, 1, 1), value: 0.5}, {date: new Date(2011, 2, 1), value: 0.6}, {date: new Date(2011, 3, 1), value: 0.7}, {date: new Date(2011, 4, 1), value: 0.8} ]; 一个合适的二等分函数可定义为: var bisect = d3.bisector(function(d) { return d.date; }).right; 然后调用bisect(data, new Date(2011, 1, 2)),返回索引。 如果你想使用不同于自然排序的方法对值进行排序,那么可以使用比较器comparator而不是访问器accessor,例如降序排序而不是升序排序的时候。 var bisect = d3.bisector(function(a, b) { return a.date - b.date; }).right;

d3.shuffle(array)

使用Fisher–Yates shuffle来把传入参数(数组)随机排序. 关联数组 关联数组和数组类似,由以名称作为键的字段和方法组成。 它包含标量数据,可用索引值来单独选择这些数据,和数组不同的是, 关联数组的索引值不是非负的整数而是任意的标量。这些标量称为Keys,可以在以后用于检索数组中的数值. JavaScript 中另一种常见数据类型就是关联数组,或者简单说就是具有一系列命名属性的对象。在Java中简称映射(键值对) map,而在Python中称为字典dictionary。JavaScript为关联数组中键(属性名称)的迭代提供一个标准机制:那就是 for…in loop。然而,注意迭代的次序是未定义的。D3提供了一些将关联数组转化为索引数组的方法。

d3.keys(object)

返回一个包含指定对象(关联数组) 属性名称的数组。返回数组的顺序未定义。

d3.values(object)

返回一个包含指定对象(关联数组) 属性值的数组。返回数组的顺序未定义。

d3.entries(object)

var entry = d3.entries({ foo: 42 }); // returns [{key: "foo", value: 42}] 返回一个包含属性名称以及值(键和值)的对象(关联数组)。每一个实体都是有键值对的对象,例如{key: "foo", value: 42}。返回数组的顺序未定义。 var entry = d3.entries({ foo: 42 }); // returns [{key: "foo", value: 42}] Maps 当你尝试在JavaScript中用空对象作为map,当内部属性名称(键)作键时,会导致unexpected behavior。比如,当你设置object["proto"] = 42时,最终不会达到你理想中的结果。又如你尝试查询给定key是否在map中定义了;"hasOwnProperty" in object 返回true,因为空对象(从对象原型)继承了hasOwnProperty方法。为避免这些问题,ES6提出了simple maps and sets 理论。直到现代浏览器支持了这些集合,你可以使用d3.map替代. 注意:不同于建议的ES6map ,d3.map的key仍然强制使用字符串,而不是严格的相等。

d3.map([object])

构建一个新的map,如果指定参数object,复制参数object对象内所有枚举属性到map中。

map.has(key)

当且仅当map有指定key的实体时返回true。注意:该值可能是null 或undefined。

map.get(key)

返回参数key的值。如果map中没有参数key相同元素,返回undefined。

map.set(key, value)

指定key的value ;返回新的value。如果map之前同样的key 有一个实体了,那么旧实体被新值替代。

map.remove(key)

map有指定key的实体,删除此实体并返回true。否则,此方法不做任何操作,返回false。

map.keys()

返回在这个map所有的键的数组。返回键的集合顺序是随机的。

map.values()

返回在这个map所有的值的数组,返回值的集合顺序是随机的。

map.entries()

返回一个map内所有键-值对象的数组。返回元素的集合顺序是随机的。任何元素的键必须是字符串类型,但值可为任何类型。

map.forEach(function)

给map中每个元素调用一个指定函数function,传递元素的键和值作为两个参数。function的this上下文是这个map。返回undefined。迭代的顺序是随机的。

map.empty()

如果map中没有元素,则返回true。

map.size()

返回map中元素的个数 Sets

d3.set([array])

新建一个集合,如果指定了array ,添加array 的字符串值到返回集合中。

set.has(value)

如果集合中具有指定参数value 字符串相同的实体,则返回true。

set.add(value)

添加指定参数value字符串 到集合中.

set.remove(value)

如果集合中含有指定参数value 字符串相同元素,返回true并删除元素。否则,这个方法不做任何操作,并返回false。

set.values()

返回一个由集合中所有字符串类型值组成的数组。数组中的值的顺序为随机的。可作为集合中唯一值的简便计算方法(去重)。例如: d3.set(["foo", "bar", "foo", "baz"]).values(); // "foo", "bar", "baz"

set.forEach(function)

给集合中每个元素调用一个指定function,传递元素的值作为参数。function的this上下文是这个集合。返回undefined,迭代的顺序是随机的。

set.empty()

如果集合中没有值,返回true。

set.size()

返回集合中值的个数。 数组的处理方法

d3.merge(arrays)

合并指定参数arrays 为一个数组,此方法和数组内置方法concat 类似;唯一不同是当你要处理二维数组时,d3.merge(arrays)方法更方便。 d3.merge([ [1], [2, 3] ]); // returns [1, 2, 3]

d3.range([start, ]stop[, step])

生成一个包含算数级数的数组,类似于Python的内置函数range。这个方法常用来遍历一个数字序列或者整型数值。例如数组中的索引。不同于Python版本,这个参数不必是整形。尽管如果它们是浮点精度类型时这个结果更加可预测。如果省略if步骤,默认值是1。如果省略start参数,默认值就是0。结果中不包含stop值。完整的形式是返回一个数字数组[start,start+step,start+2 step,…]。如果step是正的,则最后一个元素是最大的start+ istep小于stop;如果step是负的,最后一个元素是start + i*step大于stop。如果返回的数组将包含值无限多数字,就会抛出一个错误,而不是造成无限循环。

d3.permute(array, indexes)

使用指定的indexes数组返回指定数组的转置。返回数组包含indexes数组中索引对应的元素,按顺序。例如,permute(["a", "b", "c"], [1, 2, 0]) 返回 ["b", "c", "a"]。接受indexes数组的长度和array中的元素长度不一样,并且允许indexes数组重复或者省略。 这个方法可以用来按固定顺序提取对象中的值到一个数组中。(在JavaScript中indexes数组是和length有特殊关系的简单属性)。按顺序提取带键的值可以用来生成嵌套选择中的数据数组。例如,我们可以用表格形式展示上述的一些明尼苏达州大麦产量数据: var cols = ["site", "variety", "yield"]; thead.selectAll('th').data(cols) .enter().append('th').text(function (d) { return d.toUpperCase(); }); tbody.selectAll('tr').data(yields) .enter().append('tr').selectAll('td').data(function (row) { return d3.permute(row, cols); }) .enter().append('td').text(function (d) { return d; });

d3.zip(arrays…)

返回的数组的数组,其中,第i个数组包含来自每个arrays参数的第i个元素。返回的数组长度被截断为arrays的最短的数组的长度。如果arrays只包含一个数组,则返回的数组是包含一个元素的数组。不带任何参数,则返回的数组是空的。 d3.zip([1, 2], [3, 4]); // returns [[1, 3], [2, 4]]

d3.transpose(matrix)

等价于d3.zip.apply(null, matrix);使用zip操作符作为二维矩阵变换。

d3.pairs(array)

对指定参数array中元素的每个相邻对,返回元组(元素i和元素i-1)的新数组。例如: d3.pairs([1, 2, 3, 4]); // returns [[1, 2], [2, 3], [3, 4]] 如果指定参数array 中少于两个元素,则返回一个空数组。 嵌套 嵌套允许数组中的元素被组织为分层树型结构;类似SQL语句里面的GROUP BY方法,但不能多级别分组,而且输出的结果是树而不是一般的表。树的层级由key方法指定。树的叶节点可以按值来排序,而内部节点可以按键来排序。可选参数汇总(rollup)函数可以使用加法函数瓦解每个叶节点的元素. nest 操作符(d3.nest返回的对象)是可以重复使用的,不保留任何嵌套数据的引用。 例如,思考下面1931-2年间明尼苏达州(美国州名)麦田地皮的表格数据结构: 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"}, ...] 为了方便查看,可以嵌套元素首先按year然后按variety,如下: var nest = 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: ...}] 嵌套的形式可以在SVG或HTML很容易迭代和生成层次结构。

d3.nest()

创建一个新操作符。keys集合初始为空。如果map或entries 操作符在任何键函数被注册之前被调用,这个嵌套操作符通常返回输入数组。例如http://bl.ocks.org/phoebebright/raw/3176159/

nest.key(function)

注册一个新的键函数。键函数将被输入数组中的每个元素调用,并且必须返回一个用于分配元素到它的组内的字符串标识符。通常,这个函数被实现为一个简单的访问器,如上面例子中year和variety的访问器。每当一个key 被注册,它被放到一个内部键数组的末端,和由此产生的map或实体将有一个额外的层级。当前没有一个方法可以删除或查询注册的键。最近注册的键就是后续的方法的当前键。

nest.sortKeys(comparator)

使用指定的参数comparator来给当前键值排序,等效于d3.descending。如果没有指定comparator 参数键的排序则返回undefined。注意:只影响实体操作符的结果;map操作符返回键的顺序永远是undefined,无论什么比较器。 var nest = d3.nest() .key(function(d) { return d.year; }) .sortKeys(d3.ascending) .entries(yields);

nest.sortValues(comparator)

使用指定的comparator参数给叶子元素排序,等效于d3.descending。这相当于在应用nest操作符前给输入的数组排序;然而,当每一组更小时它通常是更有效的。如果没有指定值的比较器,元素则按输入数组中显示的顺序排列。通常用于map和实体的操作符。

nest.rollup(function)

为每组中的叶子元素指定汇总函数(rollup )。汇总函数的返回值会覆盖叶子值数组。不论是由map操作符返回的关联数组,还是实体操作符返回的每个实体的值属性。

nest.map(array[, mapType])

对指定的数组使用nest操作符,返回一个关联数组。返回的关联数组中每个实体对应由第一个key函数返回的不同的key值。实体值决定于注册的key函数的数量:如果有一个额外的key,值就是另外一个嵌套的关联数组;否则,值就是过滤自含有指定key值得输入数组的元素数组。 如果指定了mapType ,指定的函数就会用来构造一个map而不是返回一个简单的JavaScript对象。推荐使用d3.map 实现这个目的,例如: var yieldsByYearAndVariety = d3.nest() .key(function(d) { return d.year; }) .key(function(d) { return d.variety; }) .map(yields, d3.map); 使用d3.map而不是一个对象提供便捷(例如:返回的map含有keys和values函数),防止不寻常的键名与JavaScript内置的属性冲突,例如“proto”。

nest.entries(array)

为指定的array参数应用nest操作符,返回一个键值对数组。从概念上讲,这和对map返回的关联数组应用d3.enties操作符类似,但是这个是用于每一层而不是只有第一层(最外层)。返回数组中的每个实体对应于第一个key函数返回的不同的key值。实体值取决于注册的key函数的数量:如果有一个关联的key,值就是另外一个嵌套实体数组;否则,值就是含有指定key值得输入数组过滤得到的元素数组。嵌套的案例: http://bl.ocks.org/phoebebright/raw/3176159/

大部分由Carry on 、2014-3-29翻译 少部分由咕噜2014-11-18翻译,并校对之前的翻译。