Bomber
Bomber

Reputation: 10947

Filter nested array

I am trying to filter my events object using an id. If one of the events has a category ID matching, then I want to add it to a new object.

I am updating my original question, as the dots property is an array of objects. So the answers below will not work

I have a basic fiddle

    const selectedId = 62;
    const filteredEvents = {};
    const events = {
  "2018-01-31": {
    dots: [{
      key: "test",
      color: "red",
      categories: [{
        name: "cat 1",
        id: 59
      }, {
        name: "cat 2",
        id: 61
      }, {
        name: "cat 3",
        id: 62
      }]
    }]
  },
  "2018-02-02": {
    dots: [{
      key: "test 1",
      color: "blue",
      categories: [{
        name: "cat 1",
        id: 59
      }]
    }]
  },
  "2018-02-04": {
    dots: [{
      key: "test 2",
      color: "pink",
      categories: [{
        name: "cat 1",
        id: 59
      }]
    }, {
      key: "test 2",
      color: "pink",
      categories: [{
        name: "cat 1",
        id: 59
      }]
    }]
  }
};

Trying to filter here:

Object.keys(events).dots.categories.filter(category => {
    category.id === selectedId // remove if matching
});

I would only want this property in the filtered object as it has a category id of 62:

const events = {
  "2018-01-31": {
    dots: [{
      key: "test",
      color: "red",
      categories: [{
        name: "cat 1",
        id: 59
      }, {
        name: "cat 2",
        id: 61
      }, {
        name: "cat 3",
        id: 62
      }]
    }]
  }

Upvotes: 0

Views: 897

Answers (4)

Tek choudhary
Tek choudhary

Reputation: 178

const selectedId = 62;
const filteredEvents = {};
const events = {
  "2018-01-31": {
    dots: {
      key: "test",
      color: "red",
      categories: [{
        name: "cat 1",
        id: 59
      }, {
        name: "cat 2",
        id: 61
      }, {
        name: "cat 3",
        id: 62
      }]
    }
  },
  "2018-02-02": {
    dots: {
      key: "test 1",
      color: "blue",
      categories: [{
        name: "cat 1",
        id: 59
      }]
    }
  },
  "2018-02-04": {
    dots: {
      key: "test 2",
      color: "pink",
      categories: [{
        name: "cat 1",
        id: 59
      }]
    }
  }
};
Object.keys(events).forEach(function(element) {
   // console.log(events[element].dots.categories);
    events[element].dots.categories.forEach(function(category) {
      if (category.id === selectedId) {
        filteredEvents[element] = events[element];
      }
  });
});
console.log(filteredEvents);

Upvotes: 0

guest271314
guest271314

Reputation: 1

You can use Object.values() to convert an object to an array of values, .find() to get the object having id equal to selectedId

const results = Object.values(events).filter(({dots:{categories}}) => 
    categories.find(({id}) => id === selectedId)
).pop();

Upvotes: 1

user184994
user184994

Reputation: 18271

You can use reduce to build the new object.

// Get the key for each event
let result = Object.keys(events).reduce((result, key) => {
    // Check if the categories contain a matching ID
    if (events[key].dots.categories.some(cat => cat.id === selectedId)) {
        // Add it to the results
        result[key] = events[key];
    }
    return result;
}, {});

Here is a working snippet:

const selectedId = 62;
const filteredEvents = {};
const events = {
  "2018-01-31": {
    dots: {
      key: "test",
      color: "red",
      categories: [{
        name: "cat 1",
        id: 59
      }, {
        name: "cat 2",
        id: 61
      }, {
        name: "cat 3",
        id: 62
      }]
    }
  },
  "2018-02-02": {
    dots: {
      key: "test 1",
      color: "blue",
      categories: [{
        name: "cat 1",
        id: 59
      }]
    }
  },
  "2018-02-04": {
    dots: {
      key: "test 2",
      color: "pink",
      categories: [{
        name: "cat 1",
        id: 59
      }]
    }
  }
};


let result = Object.keys(events).reduce((result, key) => {
    if (events[key].dots.categories.some(cat => cat.id === selectedId)) {
      result[key] = events[key];
    }
    return result;
}, {});


console.log(result);

Upvotes: 1

Nina Scholz
Nina Scholz

Reputation: 386520

You could filter the keys of the object by checking if the inner array has the wanted id.

Then build a new object with the given keys.

var selectedId = 62,
    filteredEvents = {},
    events = { "2018-01-31": { dots: { key: "test", color: "red", categories: [{ name: "cat 1", id: 59 }, { name: "cat 2", id: 61 }, { name: "cat 3", id: 62 }] } }, "2018-02-02": { dots: { key: "test 1", color: "blue", categories: [{ name: "cat 1", id: 59 }] } }, "2018-02-04": { dots: { key: "test 2", color: "pink", categories: [{ name: "cat 1", id: 59 }] } } };

Object.assign(filteredEvents, ...Object
    .keys(events)
    .filter(k => events[k].dots.categories.some(({ id }) => id === selectedId))
    .map(k => ({ [k]: events[k] }))
);

console.log(filteredEvents);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 0

Related Questions