#javascript
#javascript
Вопрос:
Я успешно написал рекурсивную функцию для перебора вложенного объекта и поиска результатов. Но мне сложно добавить весь родительский элемент, если его дочерние элементы проходят тест. У меня есть следующий код:
const myObj = [
{
name: '1',
pages: [
{
name: '1.1',
pages: []
},
{
name: '1.2',
pages: []
},
]
},
{
name: '2',
pages: []
},
{
name: '3',
pages: []
}
]
function searchPages(searchQuery, obj) {
let searchResults = [];
for (let i = 0; i < obj.length; i ) {
let item = searchString(obj[i], searchQuery);
if (item) {
searchResults.push(item);
}
}
return searchResults;
}
function searchString(obj, string) {
if (obj.name.includes(string)) {
return obj;
}
for (let i = 0; i < obj.pages.length; i ) {
const possibleResult = searchString(obj.pages[i], string);
if (possibleResult) {
return possibleResu<
}
}
}
let searchResults = searchPages('1.1', myObj);
console.log(searchResults);
Это выполняет правильный поиск во вложенном массиве и дает правильный результат:
{
"name": "1.1",
"pages": []
}
Но я хотел бы вернуть весь родительский объект, а не только дочерний объект. Итак, ожидаемый результат таков:
{
name: '1',
pages: [
{
name: '1.1',
pages: []
},
{
name: '1.2',
pages: []
},
]
}
Как я могу изменить свою функцию для достижения этой цели?
Имейте в виду, что это всего лишь небольшой объект только для удобства чтения. Мой фактический объект будет иметь гораздо больше уровней и свойств.
Ответ №1:
Вы можете использовать рекурсивный подход и проверить, имеют ли вложенные массивы нужное имя.
function searchPages(array, string) {
const find = ({ name, pages }) => name.includes(string) || pages amp;amp; pages.some(find);
return array.filter(find);
}
const
data = [{ name: '1', pages: [{ name: '1.1', pages: [] }, { name: '1.2', pages: [] }] }, { name: '2', pages: [] }, { name: '3', pages: [] }],
searchResults = searchPages(data, '1.1');
console.log(searchResults);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Комментарии:
1. Спасибо за ваш ответ! кажется, это работает для меня, но есть ли способ изменить это, чтобы оно включало частичные строки? как то, что я сделал в своей функции
obj.name.includes(string)
2. вы можете заменить проверку на
includes
. пожалуйста, смотрите Редактирование.
Ответ №2:
Вот мой подход к .filter
-ing myObj
и .find
-ing вложенным страницам с заданным именем
const myObj = [
{
name: '1',
pages: [
{
name: '1.1',
pages: []
},
{
name: '1.2',
pages: []
},
]
},
{
name: '2',
pages: []
},
{
name: '3',
pages: []
}
];
const searchPages = (name, arr) => arr.filter(
({ pages }) => pages.find(page => page.name === name)
)
let searchResults = searchPages('1.1', myObj);
console.log(searchResults);
Ответ №3:
Если вы хотите вернуть родительский object
объект вместо искомого object
, вам просто нужно изменить searchString()
реализацию, чтобы она принимала родительский объект в качестве третьего параметра, а затем возвращала его, если вы находите желаемый string
:
function searchPages(searchQuery, obj) {
let searchResults = [];
for (let i = 0; i < obj.length; i ) {
let item = searchString(obj[i], searchQuery, obj);
if (item) {
searchResults.push(item);
}
}
return searchResults;
}
function searchString(obj, string, parent) {
if (obj.name.includes(string)) {
return parent;
}
for (let i = 0; i < obj.pages.length; i ) {
const possibleResult = searchString(obj.pages[i], string, obj);
if (possibleResult) {
return possibleResu<
}
}
}
Таким образом, вы всегда будете учитывать родительский элемент.
ДЕМОНСТРАЦИЯ:
const myObj = [
{
name: '1',
pages: [
{
name: '1.1',
pages: [
{
name: '1.1.1',
pages: []
}
]
},
{
name: '1.2',
pages: []
},
]
},
{
name: '2',
pages: []
},
{
name: '3',
pages: []
}
]
function searchPages(searchQuery, obj) {
let searchResults = [];
for (let i = 0; i < obj.length; i ) {
let item = searchString(obj[i], searchQuery, obj);
if (item) {
searchResults.push(item);
}
}
return searchResults;
}
function searchString(obj, string, parent) {
if (obj.name.includes(string)) {
return parent;
}
for (let i = 0; i < obj.pages.length; i ) {
const possibleResult = searchString(obj.pages[i], string, obj);
if (possibleResult) {
return possibleResu<
}
}
}
let searchResults = searchPages('1.1.1', myObj);
console.log(searchResults);
Комментарии:
1. спасибо за ответ! но это не работает с массивами, вложенными более чем на 2 уровня
2. @cup_of можете ли вы воспроизвести это на примере?
3. да, я отредактировал ваш ответ, он вернет только своего непосредственного родителя
4. @cup_of поскольку это родительский объект, вы сказали, что вам нужно вернуть родительский, а не текущий объект.
Ответ №4:
Вот один из возможных подходов, использующий .filter
для верхнего массива, за которым следуют рекурсивные вызовы .some
:
const myObj = [
{
name: '1',
pages: [
{
name: '1.1',
pages: []
},
{
name: '1.2',
pages: []
},
]
},
{
name: '2',
pages: []
},
{
name: '3',
pages: []
}
];
const searchPages = (nameToFind, obj) => obj.filter(pageContainsName(nameToFind));
const pageContainsName = nameToFind => ({ name, pages }) => (
name === nameToFind || pages.some(pageContainsName(nameToFind))
);
let searchResults = searchPages('1.1', myObj);
console.log(searchResults);