Poznajemy kolejny wzorzec, który ja nazywam depth-control. Posiada on warunek bazowy będący maksymalną głębokością, na jaką schodzi. Do dzieła.
Przypomnijmy sobie funkcję flatten:
const flatten = (nestedArr) => {
const flatArr = [];
const _flatten = (arr) => {
let counter = 0
while (counter < arr.length) {
const val = arr[counter];
if (Array.isArray(val))
_flatten(val);
else
flatArr.push(val);
counter++;
}
}
_flatten(nestedArr);
return flatArr;
}
Ta funkcja będzie spłaszczać aż do skutku, aż nie napotka elementu, który tablicą nie jest albo nie wyczerpie wszystkich elementów.
Ok, zobaczmy jak można rozpłaszczyć bardzo prostą tablicę (1 poziom zagnieżdżenia):
let oneLevelNest = [1,2, [3,4], 5, [6,7]];
let flatOneLevelNest = oneLevelNest.reduce((acc, val) => acc.concat(val), []);
console.log(flatOneLevelNest);
//[ 1, 2, 3, 4, 5, 6, 7 ]
Ok, niech o rekurencyjnym wywołaniu się funkcji decyduje warunek dotyczący typu danych (tablica), lecz o jej zakończeniu decyduje warunek bazowy dotyczący jej głębokości:
function flattenToDepth(arr, depth){
if(depth === 0)
return arr.slice();
return arr.reduce(
(acc, val) => acc.concat(Array.isArray(val) ?
flattenToDepth(val, depth - 1)
: val),
[]);
}
console.log(flattenToDepth(arr, 3));
//[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
Możemy teraz poeksperymentować. Albo napisać bez reduce, w jakiś inny sposób. Koniec końców kontrolowanie na jaką głębokość schodzimy to rzecz często w rekurencji spotykana.