Объединить два массива для фильтрации общего результата?

#javascript #arrays #reactjs #filter

#javascript #массивы #reactjs #Фильтр

Вопрос:

У меня есть два массива — фактический массив содержит 2500 записей, теперь их немного для примера). Я реализовал функцию поиска в реальном времени в react native. Это моя функция,

Таким образом, когда пользователь вводит что-либо, оно фильтрует и отображает во flatlist! Это работает отлично, но дело в том, что у меня есть другой array2, в котором у него есть псевдонимы для городов в array1 (примечание: не у всех городов есть псевдонимы). Мой вопрос в том, как объединить оба для фильтрации,

Например: когда пользователь вводит «Tiruchirapalli» или «Trichy», он должен показывать имя псевдонима, а для городов, у которых нет псевдонима, должно быть показано его оригинальное название!

Как этого добиться ?

Array1

 const array1 = [{
    "id": "117",
    "name": "Tiruchirapalli",
    "stateId": "101"
  },
  {
    "id": "27110",
    "name": "Ganoda",
    "stateId": "1405"
  },
  {
    "id": "203",
    "name": "Tenkasi",
    "stateId": "101"
  },
  {
    "id": "115",
    "name": "Thanjavur",
    "stateId": "101"
  },
];
 

Массив2

 const array2 = [{
    "id": 1850,
    "cityName": "Tenkasi",
    "aliasNames": [
      "Thenkasi"
    ]
  },
  {
    "id": 4521,
    "cityName": "Tiruchirapalli",
    "aliasNames": [
      "Trichy"
    ]
  },
  {
    "id": 115,
    "cityName": "Thanjavur",
    "aliasNames": [
      "Tanjore"
    ]
  },
];
 

Попытка

 searchFilterFunction = text => {
  this.setState({
    typedText: text
  });
  const newData = this.arrayholder.filter(item => {
    const itemData = `${item.name.toUpperCase()}`;
    const textData = text.toUpperCase();
    return itemData.indexOf(textData) > -1;
  });
  this.setState({
    data: newData
  });
};
 

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

1. Я попытался создать фрагмент, но он реагирует и неверен, поэтому я просто отформатировал

2. Если возможно, пожалуйста, предоставьте решение! @mplungjan

3. Нет, дело в том, что у меня есть два отдельных массива, я не мог понять, как объединить оба и получить единый результат

Ответ №1:

Просто пример, я думаю, вы на правильном пути. Я не определял otherIndex, но я думаю, вы поняли идею:

 searchFilterFunction = text => {
  this.setState({
    typedText: text
  });
  const newData = this.arrayholder.filter(item => {
    const itemData = `${item.name.toUpperCase()}`;
    const textData = text.toUpperCase();
    const index = itemData.indexOf(textData) > -1
    return index ? array2[index] : array1[otherIndex]
  });
  this.setState({
    data: newData
  });
};
 

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

1. Но arrayholder содержит только данные array1, у него нет данных array2 (в отдельной переменной)

Ответ №2:

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

 searchFilterFunction = text => {
      this.setState({
        typedText: text
      });
      
       // Assuming you need to show alias if exists and show name only when alias 
       // is not present
      let newData = this.arrayholder2.find(item => {
        const textData = text.toUpperCase();
        return itemD.aliasNames.filter(alias => 
              alias.toUpperCase().includes(textData)).length > 0;
      });

      if(newData === undefined) {
        // alias does not match, search name now
         newData = this.arrayholder1.find(item => {
           const itemData = `${item.name.toUpperCase()}`;
           const textData = text.toUpperCase();
           return itemData.includes(textData);
        });
      }

      this.setState({
        data: newData
      });
    };
 

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

1. «Псевдонимы» находятся в разных arrayholder? Я мог бы понять логику, лежащую в основе этих двух реализаций фильтра массива? Можете ли вы это объяснить?

2. Отредактировал свой код, теперь найдите псевдоним, сначала найдя, где в aliasName — массив, поэтому с помощью filter и condition is typedText должно присутствовать имя псевдонима (подстрока)

3. Нет, он не работает, он просто выдает ошибку как неопределенную для «item.name.toUpperCase ()»

4. Пожалуйста, поместите свой пример кода в jsdfiddle или где-нибудь еще и поделитесь ссылкой здесь, чтобы люди могли видеть и помогать

Ответ №3:

В функции сначала создайте объект из массива псевдонимов, где ключ cityName и значение aliases .

Теперь, в первом методе фильтрации массива, проверьте text совпадение как в name in, так и в соответствующем массиве псевдонимов с помощью some метода.

 const filtered = (data, aliasArr, text) => {
  const aliases = {};
  aliasArr.forEach(
    ({ cityName, aliasNames }) => (aliases[cityName] = aliasNames)
  );

  return data.filter(({ name }) => {
    return name.toUpperCase().includes(text.toUpperCase()) ||
      aliases[name]?.some((alias) =>
        alias.toUpperCase().includes(text.toUpperCase())
      );
  });
};

const array1 = [
  {
    id: "117",
    name: "Tiruchirapalli",
    stateId: "101",
  },
  {
    id: "27110",
    name: "Ganoda",
    stateId: "1405",
  },
  {
    id: "203",
    name: "Tenkasi",
    stateId: "101",
  },
  {
    id: "115",
    name: "Thanjavur",
    stateId: "101",
  },
];

const array2 = [
  {
    id: 1850,
    cityName: "Tenkasi",
    aliasNames: ["Thenkasi"],
  },
  {
    id: 4521,
    cityName: "Tiruchirapalli",
    aliasNames: ["Trichy"],
  },
  {
    id: 115,
    cityName: "Thanjavur",
    aliasNames: ["Tanjore"],
  },
];

console.log(filtered(array1, array2, 'Th'))