d3源码阅读--d3-array

Statistics

d3.min/d3.max/d3.extent

正常编写min的几种方式:

  • for循环方式
    const list = [2,4,1,4];
    let min;
    list.forEach((val, i) => {
      if (i === 0) {
        min = val;
      } else if (val < min) {
        min = val;
      }
    });
  • 使用Math.min方式
    const list = [2,4,1,4];
    const min = Math.min(...list);

源码使用了类似for循环的方式. 需要注意的是: 比较的方式只是用大于/小于, 所以如果数组由字符串, 而非完全浮点数组成, min的结果可能不是所希望的.
extent的源码和min/max类似, 返回数组的[min, max]. 如果数组为空, 则返回[undefined, undefined].

d3.sum

求数组的和. 源代码使用for循环不断相加.
也可以使用reduce来实现sum:

    const list = ['2',4,'11',4];
    const sum = list.reduce((a, b) => (+a) + (+b));

d3.mean

求平均值. 会过滤非数值型. 这里首先需要判断非数值型:

isNaN(+val)

加号会将val转换为数值型. 如果不是数值型, 会转换为NaN.
过滤掉非数值型后, 使用sum / count即可.

d3.median

求中位数. 这里调用了d3.quantile来计算中位数.

d3.variance

求样本方差.

d3.deviation

求标准差.

Search

d3.scan

求给定数组的最小值, 但允许提供比较函数(这点不同于d3.min). 源代码中关键部分的代码:

  while (++i < n) {
    if (compare(xi = values[i], xj) < 0 || compare(xj, xj) !== 0) {
      xj = xi, j = i;
    }
}
  • 将比较后的最小值存储在xj中, 然后索引递增进行排序.
  • compare(xj, xj) !== 0用于过滤undefined, null和NaN.
const array = [{foo: 42}, {foo: 91}];
d3.scan(array, function(a, b) { return a.foo - b.foo; }); // 0
d3.scan(array, function(a, b) { return b.foo - a.foo; }); // 1

d3.bisector

这里使用了二分查找法:

    left: function(a, x, lo, hi) {
      if (lo == null) lo = 0;
      if (hi == null) hi = a.length;
      while (lo < hi) {
        var mid = lo + hi >>> 1;
        if (compare(a[mid], x) < 0) lo = mid + 1;
        else hi = mid;
      }
      return lo;
},

d3.ascending/d3.descending

比较两个数的大小.

export default function(a, b) {
  return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
}

JavaScript中NaN比较特殊, 它不能进行比较. 任何和NaN比较的操作均为false.

Transformations

Histograms

你可能感兴趣的:(d3源码阅读--d3-array)