Рекурсивный перебор массива в JS
Подскажите пожалуйста, как перебрать массив с неизвестной вложенностью? Ситуация такая, практикую js и reactjs на начальном уровне, делаю приложение с покемонами и хочу вывести компонент с эволюцией :). API возвращает такой ого вида объект:
{
baby_trigger_item: null,
chain: {
evolution_details: [],
evolves_to: [
{
evolves_to: [
{
evolves_to: [],
is_baby: false,
species: {
name: "poliwrath",
url: "https://pokeapi.co/api/v2/pokemon-species/62/"
}
},
{
evolves_to: [],
is_baby: false,
species: {
name: "politoed",
url: "https://pokeapi.co/api/v2/pokemon-species/186/"
}
}
],
is_baby: false,
species: {
name: "poliwhirl",
url: "https://pokeapi.co/api/v2/pokemon-species/61/"
}
}
],
is_baby: false,
species: {
name: "poliwag",
url: "https://pokeapi.co/api/v2/pokemon-species/60/"
}
},
id: 26
};
Количество вложенных массивов "evolves_to" может быть много, а может и не быть. а еще внутри "evolves_to" может быть несколько объектов, т.е развитие как бы одного уровня в несколько видов.
На выходе должно получиться(думаю такая структура будет удобна в дальнейшей работе):
[
[
{
name: "",
url: ""
}
],
[
{
name: "",
url: ""
},
{
name: "",
url: ""
}
][
{
name: "",
url: ""
}
]
]
Т.е первый массив с первым уровнем развития, второй массив второй уровень массива с двумя видами, третий массив соответственно третий уровень и т.д. Если вложенность не известна, то нужно как-то оперировать с рекурсией? копал я в сторону map, reduce...и пытался влепить в них рекурсию... но к сожалению пока не додумался. Если не затруднит 'покажите пусть истинный'. Заранее благодарю )
Ответы (2 шт):
Здесь реализован только вывод данных, однако используя эту структуру можно легко привязать любой процесс обработки.
function printRec(obj, pref=''){
let string = pref+'->'+obj.species.name;
console.log(string)
if (!obj.evolves_to.length){
return
}
obj.evolves_to.forEach(elem=>printRec(elem, string))
}
printRec(a.chain)
Для решения данной задачи на мой взгляд вам подойдет такой подход, сочетание reduce, concat и немного рекурсии.
Проходясь по массиву с помощью итератора reduce, проверяется является ли текущее значение массивом, если да, то производится рекурсивный вызов функции, если нет, конкатенируем с аккумулирующим значением.
Таким образом, на входе массив неизвестной вложенности, на выходе одномерный массив.
const exampleArr = [1, [1, 2, [3, 4]], [5, 6]];
const toOneLevelArray = (arr) => arr.reduce((accum, currentVal) => accum.concat(Array.isArray(currentVal) ? toOneLevelArray(currentVal) : currentVal), []);
console.log(toOneLevelArray(exampleArr));