Léonie
Léonie

Reputation: 37

Filter nested array of objects by object property in d3.js

I have a meteorite landings dataset.
I nested the data in four keys, by type:

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

This is the resulting structure: data

enter image description here

Now I want to create new arrays, filtering the nested one: I want each filtered array to contain only the objects whose "mass" property is inside a defined range.
So I tried this:

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

But it returns undefined.

Nesting is giving me a lot of trouble! What do I do wrong?
Thanks in advance

Upvotes: 1

Views: 4296

Answers (4)

Ben
Ben

Reputation: 5626

I think you're overwriting lightWeight on each pass of that forEach. Instead try creating lightWeight as its own object, then adding the keys you want in the loop:

const lightWeight = {};

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

Working pen which (I think?) is doing what you want: https://codepen.io/benjaminwfox/pen/veBjrP?editors=0012

Upvotes: 3

cнŝdk
cнŝdk

Reputation: 32145

Assuming that you got the data in the format you shared, where for each item of data you have a key property and a values array.

If you want to filter the values array by the mass property of each entry, you will need to use a combination of .map() and .filter() methods.

This is how should be your code:

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;
});

This will give you the expected results.

Upvotes: 0

Stan Liu
Stan Liu

Reputation: 210

I am unsure what you are trying to filter on exactly, but try to use map instead of forEach and you need to return d in the iterators, anon function.

Like the following:

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

Upvotes: 0

Jonny Rathbone
Jonny Rathbone

Reputation: 179

I couldn't speak for what your dataset looks like, but could it just be that you're not returning lightWeight at the end?

Upvotes: 0

Related Questions