Принудительный выход из из рекурсивной функции
У меня есть объект дерева в котором я хочу найти файл, он может лежать как на каком-то уровне, так и в какой-то папке, если в папке, то я рекурсивно вызываю функцию.
Я хочу вернуть true, если файл найден, но из-за множественной рекурсии значение на выходе меняется.
На первом уровне все нормально выводит, только выше подымаюсь - выдает undefined.
let tree = {
firstLevelFirstField: {
secondLevelFirstField: 1,
secondLevelSecondField: {
thirdLevelFirstField: 'a2',
thirdLevelSecondField: {
fourthLevelFirstField: {
fifthLevelFirstField: 'a2',
fifthLevelSecondField: 5,
fifthLevelThirdField: 'School'
}
},
thirdLevelThirdField: {},
thirdLevelFourthField: 500
},
secondLevelThirdField: {},
secondLevelFourthField: {
thirdLevelFirstField: 'JavaScript',
thirdLevelSecondField: 'margin auto',
thirdLevelThirdField: '!important is evel'
},
secondLevelFifthField: 'Async'
},
firstLevelSecondField: 'easy',
firstLevelThirdField: 123,
firstLevelFourthField: {
secondLevelFirstField: 'React.js',
secondLevelSecondField: {
thirdLevelFirstField: 42
}
}
};
function FindFile(tree, file) {
for (let key in tree) {
// значения ключей
if (typeof(tree[key]) == 'object') {
FindFile(tree[key], file);
} else if (tree[key] == file) {
return true;
}
}
}
console.log(FindFile(tree, '500'));
Ответы (2 шт):
Проблема в том, что результат рекурсии не возвращается
if (typeof(tree[key]) == 'object') {
FindFile(tree[key], file);
}
здесь возвращаемое значение теряется.
Так как вызов происходит внутри цикла, если значение найдено на нижнем уровне, цикл надо прервать, и продолжить в противном случае.
Таким образом надо добавить условие
if (FindFile(tree[key], file)) // если нашли на нижнем уровне
return true;
Пример:
let tree = {
firstLevelFirstField: {
secondLevelFirstField: 1,
secondLevelSecondField: {
thirdLevelFirstField: 'a2',
thirdLevelSecondField: {
fourthLevelFirstField: {
fifthLevelFirstField: 'a2',
fifthLevelSecondField: 5,
fifthLevelThirdField: 'School'
}
},
thirdLevelThirdField: {},
thirdLevelFourthField: 500
},
secondLevelThirdField: {},
secondLevelFourthField: {
thirdLevelFirstField: 'JavaScript',
thirdLevelSecondField: 'margin auto',
thirdLevelThirdField: '!important is evel'
},
secondLevelFifthField: 'Async'
},
firstLevelSecondField: 'easy',
firstLevelThirdField: 123,
firstLevelFourthField: {
secondLevelFirstField: 'React.js',
secondLevelSecondField: {
thirdLevelFirstField: 42
}
}
};
function FindFile(tree, file) {
for (let key in tree) {
// значения ключей
if (typeof(tree[key]) == 'object') {
if (FindFile(tree[key], file)) return true;
} else if (tree[key] == file) {
return true;
}
}
}
console.log(FindFile(tree, '500'));
Не совсем изящно, но можно в условии входа в новый слой функции проверять возвращаемое значение — если оно равно true, то тогда нужно прервать выполнение, передав вышестоящему слою true.
let tree = {
firstLevelFirstField: {
secondLevelFirstField: 1,
secondLevelSecondField: {
thirdLevelFirstField: 'a2',
thirdLevelSecondField: {
fourthLevelFirstField: {
fifthLevelFirstField: 'a2',
fifthLevelSecondField: 5,
fifthLevelThirdField: 'School'
}
},
thirdLevelThirdField: {},
thirdLevelFourthField: 500
},
secondLevelThirdField: {},
secondLevelFourthField: {
thirdLevelFirstField: 'JavaScript',
thirdLevelSecondField: 'margin auto',
thirdLevelThirdField: '!important is evel'
},
secondLevelFifthField: 'Async'
},
firstLevelSecondField: 'easy',
firstLevelThirdField: 123,
firstLevelFourthField: {
secondLevelFirstField: 'React.js',
secondLevelSecondField: {
thirdLevelFirstField: 42
}
}
};
function FindFile(tree, file) {
for (let key in tree) {
// значения ключей
if (typeof(tree[key]) === 'object') {
if (FindFile(tree[key], file)) { // проверяем, если вышестоящая функция вернула true
return true // то передаём его на слой выше
}
} else if (tree[key] == file) {
return true;
}
}
}
console.log(FindFile(tree, '500'));