r1987
r1987

Reputation: 537

Remove object from array by sub array key value

I have an array of objects:

And I want to remove the object, that has a specific date (2020-09-24 in this example) in the excluded_dates Array to output the new Array like this:

  outcome = [
    {
      title: '"test1"',
      excluded_dates: false,
    },
    {
      title: '"test2"',
      excluded_dates: [
        { excluded_date: "2020-09-12" },
        {
          excluded_date: "2020-09-17",
        },
      ],
    }
   ];

For this, I was thinking of using double filtering. I also tried some(), but that is for Arrays, not an Array of Objects.

const data = [
        {
          title: '"test1"',
          excluded_dates: false,
        },
        {
          title: '"test2"',
          excluded_dates: [
            { excluded_date: "2020-09-12" },
            {
              excluded_date: "2020-09-17",
            },
          ],
        },
        {
          title: '"test3"',
          excluded_dates: [
            {
              excluded_date: "2020-09-16",
            },
            {
              excluded_date: "2020-09-24",
            },
          ],
        },
      ];



const outcome = data.filter(function (event) {
    if (event.excluded_dates) {
      return event.excluded_dates.filter(
        (date) => date.excluded_date === "2020-09-24"
      );
    }
  });

 console.log(outcome);

This ofcourse doesn't work as expected. What am I'm missing here?

Upvotes: 1

Views: 482

Answers (6)

harishprodduturi
harishprodduturi

Reputation: 46

Tried using Foreach and filter operators

const data = [
    {
      title: '"test2"',
      excluded_dates: [
        { excluded_date: "2020-09-12" },
        {
          excluded_date: "2020-09-17",
        },
      ],
    },
    {
      title: '"test3"',
      excluded_dates: [
        {
          excluded_date: "2020-09-16",
        },
        {
          excluded_date: "2020-09-24",
        },
      ],
    },
  ];
  
  
  
  data.forEach(function(item, idx) {
      item.excluded_dates.filter(function(item1) {
          if( item1.excluded_date === "2020-09-24" ) {
              
              return data.pop(idx);
          }
      });
  });
  
  console.log(data);

Upvotes: 0

Lioness100
Lioness100

Reputation: 8412

Make sure to return true if the object does not have an excluded_dates property. Also, since you are only looking for one date, you can replace your second use of Array.prototype.filter with Array.prototype.some()

const outcome = data.filter((event) => {
  return !(
    event.excluded_dates && // if there is no `excluded_dates` property, return `true`
    event.excluded_dates.some( // otherwise, try to find the date. if found, return `false`
      ({ excluded_date }) => excluded_date === "2020-09-24"
    )
  );
});

Code snippet example:

const data = [{
    title: '"test1"',
    excluded_dates: false,
  },
  {
    title: '"test2"',
    excluded_dates: [{
        excluded_date: "2020-09-12"
      },
      {
        excluded_date: "2020-09-17",
      },
    ],
  },
  {
    title: '"test3"',
    excluded_dates: [{
        excluded_date: "2020-09-16",
      },
      {
        excluded_date: "2020-09-24",
      },
    ],
  },
];

const outcome = data.filter((event) => {
  return !(
    event.excluded_dates &&
    event.excluded_dates.some(
      ({ excluded_date }) => excluded_date === "2020-09-24"
    )
  );
});

console.log(outcome);

Upvotes: 4

Remy
Remy

Reputation: 129

You were on the right track. You can even use some() for the excluded_dates array. Here is a working function

data.filter((d) => {
 if (Array.isArray(d.excluded_dates)) {
  return d.excluded_dates.some((date) => date.excluded_date === '2020-09-24');
 }

 return true;
});

Upvotes: 0

deepak
deepak

Reputation: 1375

you were at right track, only need to change the condition. Filter always return item where condition is matching. you need to check if excluded_date is false or excluded_date array doesn't contain the date. So in inner filter If we get length 0,it means date is not present in the array and so include in expected output.

const data = [{
    title: '"test1"',
    excluded_dates: false,
  },
  {
    title: '"test2"',
    excluded_dates: [{
        excluded_date: "2020-09-12"
      },
      {
        excluded_date: "2020-09-17",
      },
    ],
  },
  {
    title: '"test3"',
    excluded_dates: [{
        excluded_date: "2020-09-16",
      },
      {
        excluded_date: "2020-09-24",
      },
    ],
  },
];

const outcome = data.filter(event => (!event.excluded_dates || event.excluded_dates.filter(
    (date) => date.excluded_date === "2020-09-24"
  ).length == 0))

console.log(outcome);

Upvotes: 0

Emiel Zuurbier
Emiel Zuurbier

Reputation: 20954

Return true if event has not the excluded_dates property, because those you'll want to keep in every scenario.

Instead of a nested filter check if every excluded_date in the excluded_dates array is not equal to "2020-09-24" with the Array.prototype.every method, which returns true or false based if every callback evaluated true or not.

const data = [{
    title: '"test1"',
    excluded_dates: false,
  },
  {
    title: '"test2"',
    excluded_dates: [{
        excluded_date: "2020-09-12"
      },
      {
        excluded_date: "2020-09-17",
      },
    ],
  },
  {
    title: '"test3"',
    excluded_dates: [{
        excluded_date: "2020-09-16",
      },
      {
        excluded_date: "2020-09-24",
      },
    ],
  },
];

const outcome = data.filter(function(event) {
  if (event.excluded_dates) {
    return event.excluded_dates.every(
      (date) => date.excluded_date !== "2020-09-24"
    );
  }
  return true;
});

console.log(outcome);

Upvotes: 0

Impirator
Impirator

Reputation: 1442

I would use filter:

let data = [
  { index: 0, exclude: ['Monday'] },
  { index: 1, exclude: ['Tuesday', 'Thursday'] },
  { index: 2, exclude: ['Wednesday'] },
];

data = data.filter(el => !el.exclude.includes('Tuesday'));

console.log(data);
// data = { index: 0, exclude: ['Monday'] }, { data: 2, exclude: ['Wednesday'] }

Upvotes: 0

Related Questions