【问题标题】:Filter nested array of objects by object property in d3.js在 d3.js 中按对象属性过滤嵌套的对象数组
【发布时间】:2017-09-11 21:36:24
【问题描述】:

我有一个陨石着陆数据集。
我将数据嵌套在四个键中,按类型:

  var dataByType = d3.nest()
    .key(function(d) {
          return d.rectype;
    })
    .entries(dataset); // the original array

这是生成的结构:data

现在我想创建新数组,过滤嵌套的数组:我希望每个过滤后的数组只包含“质量”属性在定义范围内的对象.
所以我尝试了这个:

// filter small meteorites
var lightWeight = dataByType.forEach(function(d){
      d.values.filter(function (object) {
            var mass = object.mass;
            return mass <= 100;
      });
  });

但它返回 undefined

嵌套给我带来了很多麻烦!我做错了什么?
提前致谢

【问题讨论】:

  • 尝试使用map 而不是forEach 并返回d。喜欢var lightWeight = dataByType.map(function(d){ d.values.filter(function (object) { var mass = object.mass; return mass &lt;= 100; }); return d; });
  • 请将您的数据发布为文本而不是图像。
  • 你的 d.values 是一个数组所以....d.values[1].filter?
  • @ben 我试过forEach(function(d, i){ d.values[i].filter(...) 但它返回一个错误说“d.values[i].filter 不是一个函数”
  • @chsdk 对不起,我是新手,不知道如何从 Firefox 控制台进行操作

标签: javascript arrays d3.js filter


【解决方案1】:

我认为您在 forEach 的每次传递中都覆盖了 lightWeight。而是尝试将 lightWeight 创建为自己的对象,然后在循环中添加所需的键:

const lightWeight = {};

dataByType.forEach(function(d){
  lightWeight[d.key] = d.values.filter(function (object) {
    var mass = object.mass;
    return mass <= 100;
  });
});

(我认为?)正在做你想做的事情的工作笔: https://codepen.io/benjaminwfox/pen/veBjrP?editors=0012

【讨论】:

  • 非常感谢,这正是我所需要的!所以我的错误是没有将结果分配给循环内的键。但是,为什么我得到未定义而不是只有最后一个结果的数组?将 lightWeight 声明为 const 而不是 var 重要吗?
  • const vs var 是两个 JavaScript 版本(ES6 vs ES5)之间的语法差异。这实际上与解决方案无关,它只是我最近一直在使用的语法。我会看看能否解释为什么它最终未定义。
  • 所以你得到未定义的原因是因为你试图分配一个 forEach 循环的返回值,设计它返回未定义。请参阅 MDN 页面:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…,以及有关 SO 问题的更多信息:stackoverflow.com/questions/34653612/… 您的 .filter() 函数仅返回 forEach 循环范围内的质量值。
  • 非常感谢您的耐心等待!
【解决方案2】:

我无法说明您的数据集是什么样的,但可能只是您最后没有返回 lightWeight 吗?

【讨论】:

    【解决方案3】:

    我不确定您要过滤的确切内容,但请尝试使用map 而不是forEach,并且您需要在迭代器、匿名函数中返回d

    如下:

    var lightWeight = dataByType.map(function(d) {
        d.filteredValues = d.values.filter(function (object) {
            return object.mass <= 100;
        });
        return d;
    });
    

    【讨论】:

    • 其实filter()方法会返回一个新的array并且不会改变数组in-place,所以这段代码不会有帮助。
    • 如果你将它存储在对象内的另一个键中,比如filteredValues
    • 这将影响初始数组结构,但如果您愿意,可以以任何方式执行d.values = d.values.filter(...)
    • @StanleyLiu 是的,这可行,但会更改原始数组。不过,最后,我只需要按质量值的 5 个区间对数据进行分组,这样就可以了。我只是希望它不会使以后访问数据变得更加困难。我会尽力!谢谢
    【解决方案4】:

    假设您获得了共享格式的data,其中data 的每个项目都有一个key 属性和一个values 数组。

    如果您想通过每个条目的mass 属性过滤values 数组,则需要结合使用.map().filter() 方法。

    这应该是你的代码:

    var lightWeight = data.map(function(d){
        var obj = {};
        obj.key = d.key;
        obj.values = d.values.filter(function (object) {
                return object.mass <= 100;
        });
        return obj;
    });
    

    这将为您提供预期的结果。

    【讨论】:

    • 我试过了,但仍然出现错误提示“d.values is undefined”
    • @Léonie 通常这会很好地工作,您能否给我们展示一个您遇到此错误的 Demo,您使用了哪些数据?
    猜你喜欢
    • 1970-01-01
    • 2018-01-16
    • 2021-09-27
    • 1970-01-01
    • 1970-01-01
    • 2021-07-08
    • 1970-01-01
    • 2020-03-11
    • 2021-10-27
    相关资源
    最近更新 更多