Poznajemy odmianę wzorca arr-handler-loop. Wzorzec arr-handler-loop-deeperOrPush pokaże nam, jak możemy rozpłaszczyć tablicę. Do dzieła.

Najpierw wzorzec z poprzedniej lekcji:

function getTextNodes(el){
    
    var textNodes = []
    
    function handler(node){
        if(node === null)
            return;

        if(node.nodeType === Node.TEXT_NODE)
            textNodes.push(node);

        if(node.nodeType !== Node.TEXT_NODE){
            node.childNodes.forEach((childNode) => {
                handler(childNode);
            });
        }
    }

    handler(el);

    return textNodes;
}

Rozumiemy ogólną logikę. Teraz piszemy funkcję robiącą Arr.flat:

  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;
  }

  let arr = [1,2,[3],[4,5],6,[7,[8,[9,10]]]];
  console.log(flatten(arr)); 
  //Array(10) [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]

Zasada prosta:

  • Tablica, handler, handler, tablica
  • Handler bierze tablicę i bez ceregieli zaczyna iterację po niej
  • Jeżeli element tablicy jest tablicą to to zostaje przekazany rekurencyjnie do handlera
  • Jeżeli jest zwykłym elementem, zostaje dopisany do tej wyjściowej
  • Handler wywołany na pierwotnie przekazanej tablicy i wynik zwrócony
  • Wszystko działa dzięki closures.
  • Zwróćmy uwagę, że np. w PHP nasza funkcja handler musiałaby mieć „use ($flatArr)” żeby mieć dostęp do tej tablicy poziom wyżej. W różnych językach jest różnie.