Поиск по массиву в объекте JavaScript

89
08 марта 2022, 01:30

Есть массив объектов, который имеет в себе ещё один массив, по которому нужно совершить поиск. Структура данных выглядит вот так:

[
    {
        topic: "First",
        pages: [
            "Alpha",
            "Beta",
            "Gamma",
            "Delta"
        ],
        id: ["1", "2", "3", "4"]
    },
    {
        topic: "Second",
        pages: [
            "Epsilon",
            "Zeta",
            "Eta",
            "Theta"
        ]
        id: ["5", "6", "7", "8"]
    }
]

Нужно по заданному значению совершить поиск в массивах pages, и в случае успешного нахождения элемента вернуть его id из следующего массива. Каждый id соответствует по индексу элементу из первого массива ("Alpha"-"1", "Epsilon"-"5"). Есть ли какая-либо JS библиотека для подобного поиска? Пробовал Fuse.js, но она после поиска возвращает сам объект из массива, но мне нужно, чтобы возвращаемым элементом была строка из массива pages (или её id), а не весь объект. На вход подаётся любая строка, например 'Zeta'. Поиск должен быть осуществлён по всем строкам массивов pages, и он должен вернуть индексы всех совпадений из этих массивов, в случае из примера - '6'.

Answer 1

не понимаю зачем ради такого тащить библиотеку, вот пример решения:

const myTopics = [ 
  { 
    topic: "First", 
    pages: ["Alpha", "Beta", "Gamma", "Delta"], 
    id: ["1", "2", "3", "4"] 
  }, 
  { 
    topic: "Second", 
    pages: ["Epsilon", "Beta", "Eta", "Theta"], 
    id: ["5", "6", "7", "8"] 
  } 
]; 
 
function innerArraySearch(topicsArray, pageToSearch) { 
  let answer = []; // ответ по умолчанию 
  topicsArray.map(topic => { 
    // проходим по верхнему массиву 
    const indexOfPage = topic.pages.indexOf(pageToSearch); // записываем индекс (не)найденного элемента массива pages 
    if (indexOfPage !== -1) { 
      answer.push(topic.id[indexOfPage]); // записываем в переменную answer значение topic.id по индексу indexOfPage 
    } 
  }); 
  return answer; // возврат по умолчанию 
} 
 
console.log(innerArraySearch(myTopics, "Beta"));

Answer 2

var arrOfObj = [ 
    { 
        topic: "First", 
        pages: ["Alpha", "Beta", "Gamma", "Delta"], 
        id: ["1", "2", "3", "4"] 
    }, 
    { 
        topic: "Second", 
        pages: ["Epsilon", "Zeta", "Eta", "Theta"], 
        id: ["5", "6", "7", "8"] 
    } 
], 
findPageIndex = function(arr, pageName) { 
  var res = []; 
  for(var i = 0; i < arr.length; i++) { 
    var idx = arr[i].pages.indexOf(pageName); 
    if(idx != -1){ 
      res.push({ 
        topic: arr[i].topic, 
        idx: idx, 
        id: arr[i].id[idx] 
      }); 
    } 
  } 
  return res.length > 0 ? res : -1; 
} 
 
console.log(findPageIndex(arrOfObj, "Zeta"));

Answer 3

Можно так, например:

const data = [{ 
    topic: "First", 
    pages: [ 
      "Alpha", 
      "Beta", 
      "Gamma", 
      "Delta" 
    ], 
    id: ["1", "2", "3", "4"] 
  }, 
  { 
    topic: "Second", 
    pages: [ 
      "Epsilon", 
      "Zeta", 
      "Eta", 
      "Theta" 
    ], 
    id: ["5", "6", "7", "8"] 
  }, 
  { 
    topic: "Third", 
    pages: [ 
      "Iota", 
      "Kappa", 
      "Lambda", 
      "Zeta", 
      "Zeta" 
    ], 
    id: ["9", "10", "11", "12", "13"] 
  } 
]; 
 
let query = 'Zeta'; 
let result = data.reduce((acc, item) => { 
  let pageIds = item.pages.reduce((ids, page, ind, arr) => { 
    if (page == query) { // или page.includes(query), если нужен поиск по подстроке) 
      ids.push(item.id[ind]) 
    } 
    return ids; 
  }, []) 
  return acc.concat(pageIds); 
}, []).join(','); 
console.log(result);

READ ALSO
Обработать нажатие клавиши по таймеру

Обработать нажатие клавиши по таймеру

Пытаюсь реализовать живой поиск на Angular

118
Инициализировать слайдер swiper во Vue.js

Инициализировать слайдер swiper во Vue.js

Как при получении результата в методе getUser() переинициализировать swiper?

156
Выделение активного пункта меню

Выделение активного пункта меню

Имеется следующий код меню:

140
Фильтр по чекбоксам

Фильтр по чекбоксам

Я пытаюсь отсортировать данные с джсона по чекбоксамПример данных:

145