Как отфильтровать значения массива состояний на основе элементов, находящихся в другом массиве в состоянии? - PullRequest
1 голос
/ 03 мая 2020

У меня есть данные о состоянии, которые выглядят так:

 state = {
      search: “”
      tagValue: “”
      data: [
           {  
              id: 1,
              fName: "Henry",
              lName: "Jones"
              email: “lol@hotmail.com”,
              gpa: “3.6”
              tag: [
                   "hello", "bye"
              ] 
           },
           {  
              fName: "Jeffrey",
              lName: "Johnston”,
              email: “hehdbejeu@gmail.com”,
              gpa: “2.6”,
              tag: [
                   "hello", "bye"
              ] 
           },
           {  
              fName: "Henry",
              lName: "Jones"
              gpa: “1.9”
              tag: [
              ] 
           }
      ]
  }

Я выяснил, как отфильтровать массив данных на основе пользовательского ввода, выполнив:

 let studentListFilter = this.state.data.filter((student) => {
       return (
         student.firstName
           .toLowerCase()
           .indexOf(this.state.search.toLowerCase()) !== -1 ||
         student.lastName
           .toLowerCase()
           .indexOf(this.state.search.toLowerCase()) !== -1
 }

, а затем возвращая studentListFilter в моем методе рендеринга. search - это значение состояния, которое обновляется на основе пользовательского ввода. Но у меня возникают проблемы с выяснением того, как сравнить значения, расположенные в массиве, в частности, с тегом, в данном случае, с пользовательским вводом.

Я пытался сделать это безрезультатно:

let studentListFilter = this.state.data.filter((student) => {
      return (
        student.fName
          .toLowerCase()
          .indexOf(this.state.search.toLowerCase()) !== -1 ||
        student.lName
          .toLowerCase()
          .indexOf(this.state.search.toLowerCase()) !== -1 ||
        student.tag.map(
          (individualTag) =>
            individualTag
              .toLowerCase()
              .indexOf(this.state.tagValue.toLowerCase()) !== -1
        )
      );
    });

Любая помощь будет отличной

Ответы [ 2 ]

1 голос
/ 03 мая 2020

Одна из проблем заключается в том, что при проверке, включает ли любое из строковых значений входные данные фильтрации, все ли строки содержат пустую строку.

console.log("test".indexOf('') !== -1);
console.log("test".includes(''));

Таким образом, проблема возникает, когда у вас есть два входных фильтра и предположите, когда они применяются к данным. Поскольку вышеупомянутое, то одно из ваших условий всегда выполняется, если один из входов пуст и, следовательно, данные никогда не фильтруются.

  1. Необходимо изменить предположение о пустых строках фильтра, если они пусты, то нет Фильтрация должна выполняться, поэтому применять поиск можно только в том случае, если строки фильтров верны, ie. непустые строки.
  2. Первый условный тест, если оба фильтры активны, чтобы разорвать связи
  3. Второй тест каждого условия по отдельности
  4. Вернуть true, чтобы не фильтровать данные вообще

Фильтр логи c:

this.state.data
  .filter(student => {
    if (this.state.search && this.state.tagValue) {
      return (
        (student.fName.toLowerCase().includes(this.state.search) ||
          student.lName.toLowerCase().includes(this.state.search)) &&
        student.tag.some(tag => tag.toLowerCase().includes(this.state.tagValue))
      );
    }
    if (this.state.search) {
      return (
        student.fName.toLowerCase().includes(this.state.search) ||
        student.lName.toLowerCase().includes(this.state.search)
      );
    }
    if (this.state.tagValue) {
      return student.tag.some(tag =>
        tag.toLowerCase().includes(this.state.tagValue)
      );
    }
    return true;
  })

Как видно, много повторений, немного больше DRY подхода:

{this.state.data
  .filter(({ fName, lName, tag }) => {
    const includesName = [fName.toLowerCase(), lName.toLowerCase()].some(
      name => name.includes(this.state.search)
    );
    const includesTag = tag.some(tag =>
      tag.toLowerCase().includes(this.state.tagValue)
    );

    if (search && tagValue) {
      return includesName && includesTag;
    }
    if (search) {
      return includesName;
    }
    if (tagValue) {
      return includesTag;
    }
    return true;
  })

Edit multi-property filter demo

0 голосов
/ 03 мая 2020

в основном вы можете использовать некоторые для вашего случая использования:

примерно так:

    let studentListFilter = this.state.data.filter((student) => {
      const matchFirstName = student.fName
        .toLowerCase()
        .indexOf(this.state.search.toLowerCase()) !== -1;

      const matchLastName = student.lName
        .toLowerCase()
        .indexOf(this.state.search.toLowerCase()) !== -1

      // will return true if one of your tags match the search
      const someFnCB = (individualTag) => {
 return individualTag.toLowerCase().indexOf(this.state.search.toLowerCase()) !== -1 
};


      const matchTag = student.tag.some(someFnCB)


      return matchFirstName || matchLastName || matchTag;
    });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...