Сравнить два массива и показать элементы первого массива, которые имеют ключ из второго массива

#arrays #reactjs #filter #mapping

#массивы #reactjs #Фильтр #сопоставление

Вопрос:

У меня есть два разных массива, один из которых содержит все данные, которые я использую в списке, а другой, который содержит только значения из фильтра, который я разрешаю пользователю выбирать. Итак, мой первый массив — это этот:

 messages=[
{id:1, description:'abc', status:'SENT'},
{id:2, description:'hello', status:'CANCELED'},
{id:1, description:'bye', status:'SENT'}];
  

И мой второй массив — это этот:

 items = ["SENT", "CLOSED", "RECEIVED"];
  

У меня есть этот хук для установки данных, которые прямо сейчас имеют все это:

 const [messageData, setMessageData] = useState([]);
  

И что я пытаюсь сделать, это установить на моем крючке объекты первого массива, которые имеют в качестве статуса то же значение, что и один из элементов в моем втором массиве (items), чтобы я мог позже создать карту MessageData при моем рендеринге, в этом случае я должен отобразить объекты первого массива.первая и третья записи моего массива сообщений, потому что они имеют статус «ОТПРАВЛЕНО», и это значение находится в моем массиве элементов.

Дело в том, что я не знаю, как сравнивать и получать эти результаты, я попытался выполнить сопоставление массива сообщений и отфильтровать элементы, которые имели в качестве состояния одно из значений массива элементов, например:

 let search = [];
messages
.filter((option) => {
 return(
  option.value.status = items.value
 )
})
.map((option) => {
   search.push(option);
})
   setMessageData(search);
  

Но это не работает, и я не уверен, как это решить, кто-нибудь может мне помочь с этим?

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

1. У ваших messages элементов нет value свойства, только status свойство

2. Также вы используете = для сравнения, используйте ==

3. Я использовал == , но, возможно, я удалил по ошибке, когда вставлял свой код, и да, items.value был неправильным, спасибо!

Ответ №1:

Это хорошая ситуация для reduce()

Метод reduce() выполняет функцию редуктора (которую вы предоставляете) для каждого элемента массива, в результате чего получается одно выходное значение.

Array.prototype.reduce()

Вызов reduce() массива items выполняет итерацию по каждому элементу и накапливает результаты переданной логики.

В приведенном ниже примере накопитель acc инициализируется как пустой массив путем передачи [] в качестве второго аргумента в reduce() вызове.

 const messages=[
{id:1, description:'abc', status:'SENT'},
{id:2, description:'hello', status:'CANCELED'},
{id:1, description:'bye', status:'SENT'}];

const items = ["SENT", "CLOSED", "RECEIVED"];

// iterate over each 'status' in the items array
let search = items.reduce((acc, status) => {

  // retrieve objects from the messages array that match
  const matches = messages.filter(message => message.status === status);
  
  if (matches.length > 0) {
    // if matches were found concat the returned array with the accumulator
    acc = acc.concat(matches);
  }
  
  // return the accumulator to be used in the next iteration
  return acc;
  
}, []);

console.log(search)  


Превратить его в функцию

В ответ на ваш комментарий о получении разных результатов я превратил его в функцию, позволяющую легко проверять результаты из разных statusArray s, и reduce() вызов работает, как ожидалось.

 const messages=[
{id:1, description:'abc', status:'SENT'},
{id:2, description:'hello', status:'CANCELED'},
{id:1, description:'bye', status:'RECEIVED'},
{id:1, description:'xyz', status:'SENT'},
{id:2, description:'hi', status:'SENT'},
{id:1, description:'bye again', status:'RECEIVED'}];


function filterMessagesByStatus(statusArray) {
  if (!Array.isArray(statusArray)) return;  
  
  return statusArray.reduce((acc, status) => {
    const matches = messages.filter(message => message.status === status);
    if (matches.length > 0) {
      acc = acc.concat(matches);
    }
    return acc;
  }, []); 
}

console.log(filterMessagesByStatus(["SENT", "CANCELED", "RECEIVED"]));
console.log(filterMessagesByStatus(["SENT"]));
console.log(filterMessagesByStatus(["CANCELED", "RECEIVED"]));
console.log(filterMessagesByStatus(["SENT", "CANCELED", "RECEIVED"]));  

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

1. Это сработало отлично! большое спасибо за исправления, а также за объяснение каждого шага

2. Однако у меня есть вопрос, потому что, когда я ищу элементы со статусом «ОТПРАВИТЬ», он показывает мне два объекта, затем я ищу «ОТМЕНЕНО» и ничего не показывает, и если я вернусь и снова выберу «ОТПРАВИТЬ», он продолжает показывать мне 0 результатов. Как я могу предотвратить это?

3. Обновил мой ответ, чтобы протестировать разные поисковые массивы, и он работает так, как ожидалось. Я могу только догадываться, что, возможно, вы искали «ОТПРАВИТЬ» вместо «ОТПРАВЛЕНО». Также filter чувствителен к регистру.