Удаление объекта из массива по значению ключа вложенного массива

#javascript #arrays

#javascript #массивы

Вопрос:

У меня есть массив объектов:

И я хочу удалить объект, который имеет определенную дату (2020-09-24 в этом примере) в массиве excluded_dates, чтобы вывести новый массив следующим образом:

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

Для этого я думал об использовании двойной фильтрации. Я также пробовал some() , но это для массивов, а не для массива объектов.

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

Это, конечно, работает не так, как ожидалось. Чего мне здесь не хватает?

Ответ №1:

Обязательно возвращайте true , если у объекта нет excluded_dates свойства. Кроме того, поскольку вы ищете только одну дату, вы можете заменить свое второе использование Array.prototype.filter на Array.prototype.some()

 const outcome = data.filter((event) => {
  return !(
    event.excluded_dates amp;amp; // 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"
    )
  );
});
  

Пример фрагмента кода:

 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 amp;amp;
    event.excluded_dates.some(
      ({ excluded_date }) => excluded_date === "2020-09-24"
    )
  );
});

console.log(outcome);  

Комментарии:

1. Это работает, но можете ли вы объяснить, что делает этот код? У вас есть сокращение, чтобы проверить, существуют ли excluded_dates , но почему вы возвращаете true для else ?

2. Array.prototype.filter() запускает заданную функцию через каждый элемент массива. Если функция вернется true , она сохранит элемент в массиве. В противном случае он удалит его из массива.

Ответ №2:

Я бы использовал 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'] }  

Ответ №3:

Верните true , если событие не excluded_dates имеет свойства, потому что те, которые вы захотите сохранить в каждом сценарии.

Вместо вложенного фильтра проверьте excluded_date , не равно ли каждое значение в excluded_dates массиве "2020-09-24" с Array.prototype.every помощью метода, который возвращает true или false на основе того, оценивается ли каждый обратный вызов true или нет.

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

Ответ №4:

вы были на правильном пути, нужно только изменить условие. Фильтр всегда возвращает элемент, условие которого соответствует. вам нужно проверить, является ли значение excluded_date ложным или массив excluded_date не содержит даты. Итак, во внутреннем фильтре, если мы получаем длину 0, это означает, что date отсутствует в массиве и поэтому включается в ожидаемый результат.

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

Ответ №5:

Вы были на правильном пути. Вы даже можете использовать some() для массива excluded_dates . Вот рабочая функция

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

 return true;
});
  

Ответ №6:

Пробовал использовать операторы Foreach и filter

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