【问题标题】:Nesting d3.max with array of arrays用数组数组嵌套 d3.max
【发布时间】:2016-06-07 20:43:20
【问题描述】:

我有一个这样的数组数组。

data = [
  [
    {x: 1, y: 40},
    {x: 2, y: 43},
    {x: 3, y: 12},
    {x: 4, y: 60},
    {x: 5, y: 63},
    {x: 6, y: 23}
 ], [
    {x: 1, y: 12},
    {x: 2, y: 5},
    {x: 3, y: 23},
    {x: 4, y: 18},
    {x: 5, y: 73},
    {x: 6, y: 27}
 ], [
    {x: 1, y: 60},
    {x: 2, y: 49},
    {x: 3, y: 16},
    {x: 4, y: 20},
    {x: 5, y: 92},
    {x: 6, y: 20}
  ] 
];

我可以通过嵌套的 d3.max() 调用找到 data 的最大 y 值:

d3.max(data, function(d) {
  return d3.max(d, function(d) {
    return d.y;
  });
});

我很难理解这段代码的实际工作原理。我知道 d3.max() 函数的第二个参数指定了一个访问器函数 - 但我对两次调用 d3.max() 与访问器函数的关系感到困惑。

我想我要的是关于 javascript 如何解释此代码的演练。我已经在控制台上浏览了它,但不幸的是它没有帮助。

【问题讨论】:

    标签: javascript arrays d3.js


    【解决方案1】:

    有时这完全是关于变量的命名:

    // the outer function iterates over the outer array
    // which we can think of as an array of rows
    
    d3.max(data, function(row) {
    
      // while the inner function iterates over the inner
      // array, which we can think of as an array containing
      // the columns of a single row. Sometimes also called
      // a (table) cell.
    
      return d3.max(row, function(column) {
        return column.y;
      });
    
    });
    

    您可以在此处找到 d3.max 函数的源代码:https://github.com/d3/d3.github.com/blob/8f6ca19c42251ec27031376ba9168f23b9546de4/d3.v3.js#L69

    【讨论】:

    • 这是一个非常清楚的解释。变量的名称如何极大地影响对特定代码的理解,这真是令人惊讶!
    • 谢谢。我想我们刚刚看到了“寻找合适的名称问题”的一个实例。
    【解决方案2】:

    哇..!有趣的问题。出于一些体育目的,这里是通过发明一个名为Array.prototype.maxByKey() 的数组方法来解决这个问题的 ES6 解决方案,所以在这里你可以看到它实际上是如何由纯 JS 实现的。

    Array.prototype.maxByKey = function(k) {
      var m = this.reduce((m,o,i) => o[k] > m[1] ? [i,o[k]] : m ,[0,Number.MIN_VALUE]);
      return this[m[0]];
    };
    var data = [
    [{x: 1, y: 40},{x: 2, y: 43},{x: 3, y: 12},{x: 4, y: 60},{x: 5, y: 63},{x: 6, y: 23}],
    [{x: 1, y: 12},{x: 2, y: 5},{x: 3, y: 23},{x: 4, y: 18},{x: 5, y: 73},{x: 6, y: 27}],
    [{x: 1, y: 60},{x: 2, y: 49},{x: 3, y: 16},{x: 4, y: 20},{x: 5, y: 92},{x: 6, y: 20}]
    ],
    maxObj = data.map(a => a.maxByKey("y")).maxByKey("y");
    console.log(maxObj);

    以下是这段代码中发生的事情的故事。我们将通过归约找到对象的索引。我们的 reduce 方法使用了一个初始值,即数组[0,Number.MIN_VALUE],它在索引 0 处为 0,在索引 1 处具有 JS 中可能的最小数字。初始值设置为第一个参数。所以这里m 是从初始值开始的。 Reduce 将逐个遍历数组项(在我们的例子中为对象),每次o 将分配给当前对象,最后一个参数i 当然是我们当前正在处理的位置的索引。 k 被提供给我们的函数作为我们将用来测试最大值的键。

    所以有一个简单的三元比较o[k] > m[1] ? [i,o[k]] : m 这意味着检查k (o[k]) 给出的当前对象属性是否小于m[1](其中m 在第一轮中是[0,Number.MIN_VALUE] )将m作为[i,o[k]]返回(检查三元组如何返回结果)如果不小于m[1],则按原样返回m。在遍历结束时,我们将在该数组中减少到 [index of the element with max k property value, the value of that k property]

    如您所见,它非常简单。

    【讨论】:

    • @paradite 好的,是的,你是对的。它看起来很神秘,但实际上非常简单。我在答案中添加了一些解释。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-12
    • 1970-01-01
    • 1970-01-01
    • 2015-05-08
    • 1970-01-01
    相关资源
    最近更新 更多