Loop through multidimensional array with childrens and build map of paths

Viewed 56

I have the multidimensional array with childrens (subcategories):

I build Angular routing and get this data format from API.

const items = [{
  displayName: 'Wiadomości',
  urlName: 'wiadomosci',
  subcategories: [{
    displayName: 'Newsy',
    urlName: 'newsy',
    subcategories: []
  }, {
    displayName: 'Wydarzenia',
    urlName: 'wydarzenia',
    subcategories: []
  }, {
    displayName: 'Komentarze i analizy',
    urlName: 'komentarze-i-analizy',
    subcategories: []
  }, {
    displayName: 'Reportaże',
    urlName: 'reportaze',
    subcategories: []
  }]
}, {
  displayName: 'Prawo',
  urlName: 'prawo',
  subcategories: [{
    displayName: 'Sprzedaż/zakup',
    urlName: 'sprzedaz-zakup',
    subcategories: [{
      displayName: 'Dom',
      urlName: 'dom',
      subcategories: []
    }, {
      displayName: 'Mieszkanie',
      urlName: 'mieszkanie',
      subcategories: []
    }, {
      displayName: 'Działka',
      urlName: 'dzialka',
      subcategories: []
    }, {
      displayName: 'Komercyjne',
      urlName: 'komercyjne',
      subcategories: []
    }]
  }, {
    displayName: 'Najem/dzierżawa',
    urlName: 'najem-dzierzawa',
    subcategories: [{
      displayName: 'Dom',
      urlName: 'dom',
      subcategories: []
    }, {
      displayName: 'Mieszkanie',
      urlName: 'mieszkanie',
      subcategories: []
    }, {
      displayName: 'Prywatny/komercyjny',
      urlName: 'prywatny-komercyjny',
      subcategories: []
    }, {
      displayName: 'Działka',
      urlName: 'dzialka',
      subcategories: []
    }, {
      displayName: 'Budynki',
      urlName: 'budynki',
      subcategories: []
    }]
  }, {
    displayName: 'Podatki',
    urlName: 'podatki',
    subcategories: []
  }, {
    displayName: 'Prawo budowlane',
    urlName: 'prawo-budowlane',
    subcategories: []
  }, {
    displayName: 'Dziedziczenie',
    urlName: 'dziedziczenie',
    subcategories: []
  }, {
    displayName: 'Wzory dokumentów',
    urlName: 'wzory-dokumentow',
    subcategories: []
  }]
}, {
  displayName: 'Finanse',
  urlName: 'finanse',
  subcategories: [{
    displayName: 'Kredyty',
    urlName: 'kredyty',
    subcategories: []
  }, {
    displayName: 'Ubezpieczenia',
    urlName: 'ubezpieczenia',
    subcategories: []
  }, {
    displayName: 'Kalkulatory',
    urlName: 'kalkulatory',
    subcategories: []
  }, {
    displayName: 'Inwestycje',
    urlName: 'inwestycje',
    subcategories: []
  }, {
    displayName: 'Dofinansowanie i dotacje',
    urlName: 'dofinansowanie-i-dotacje',
    subcategories: []
  }]
}, {
  displayName: 'Porady i inspiracje',
  urlName: 'porady-i-inspiracje',
  subcategories: [{
    displayName: 'Budowa i remont',
    urlName: 'budowa-i-remont',
    subcategories: []
  }, {
    displayName: 'Użytkowanie',
    urlName: 'uzytkowanie',
    subcategories: []
  }, {
    displayName: 'Balkon i ogród',
    urlName: 'balkon-i-ogrod',
    subcategories: []
  }, {
    displayName: 'Aranżacje',
    urlName: 'aranzacje',
    subcategories: []
  }, {
    displayName: 'Design',
    urlName: 'design',
    subcategories: []
  }]
}, {
  displayName: 'Eksperci',
  urlName: 'eksperci',
  subcategories: [{
    displayName: 'Felietony',
    urlName: 'felietony',
    subcategories: []
  }, {
    displayName: 'Zapytaj eksperta',
    urlName: 'zapytaj-eksperta',
    subcategories: []
  }, {
    displayName: 'Materiały źródłowe',
    urlName: 'materialy-zrodlowe',
    subcategories: []
  }]
}];

I absolutely need to map the response from the server to an array that contains paths built from subcategories and urlName.

The output should be:

const paths = [
   'wiadomosci',
   'wiadomosci/newsy'
   'wiadomosci/komentarze-i-analizy',
   'wiadomosci/reportaze',
   'prawo',
   'prawo/sprzedaz-zakup',
   'prawo/sprzedaz-zakup/dom',
   'prawo/sprzedaz-zakup/mieszkanie',
   'prawo/sprzedaz-zakup/dzialka',
   'prawo/sprzedaz-zakup/komercyjne',
   'prawo/najem-dzierzawa',
   'prawo/najem-dzierzawa/dom',
   'prawo/najem-dzierzawa/mieszkanie',
   'prawo/najem-dzierzawa/prywatny-komercyjny',
   'prawo/najem-dzierzawa/dzialka',
   'prawo/najem-dzierzawa/budynki',
   'podatki',
   'prawo-budowlane',
   'dziedziczenie',
   'wzory-dokumentow',
   'finanse',
   'finanse/kredyty',
   'finanse/ubezpieczenia',
   'finanse/kalkulatory',
   'finanse/inwestycje',
   'finanse/dofinansowanie-i-dotacje',
   'porady-i-inspiracje',
   'porady-i-inspiracje/budowa-i-remont',
   'porady-i-inspiracje/uzytkowanie',
   'porady-i-inspiracje/balkon-i-ogrod',
   'porady-i-inspiracje/aranzacje',
   'porady-i-inspiracje/design',
   'eksperci',
   'eksperci/felietony',
   'eksperci/zapytaj-eksperta',
   'eksperci/materialy-zrodlowe'
];

I have tried to write recursive functions that will collect and build paths for me, but unfortunately I fail ...

Can you help me with this? :/

My try in PHP: http://sandbox.onlinephpfunctions.com/code/a2c4fc7dbddd226d0ec09e7ac020adc2d3c1d6dc

2 Answers

You could take a compact approach by mapping the nested pathes by taking a prefix for all nested objects.

const
    items = [{ displayName: 'Wiadomości', urlName: 'wiadomosci', subcategories: [{ displayName: 'Newsy', urlName: 'newsy', subcategories: [] }, { displayName: 'Wydarzenia', urlName: 'wydarzenia', subcategories: [] }, { displayName: 'Komentarze i analizy', urlName: 'komentarze-i-analizy', subcategories: [] }, { displayName: 'Reportaże', urlName: 'reportaze', subcategories: [] }] }, { displayName: 'Prawo', urlName: 'prawo', subcategories: [{ displayName: 'Sprzedaż/zakup', urlName: 'sprzedaz-zakup', subcategories: [{ displayName: 'Dom', urlName: 'dom', subcategories: [] }, { displayName: 'Mieszkanie', urlName: 'mieszkanie', subcategories: [] }, { displayName: 'Działka', urlName: 'dzialka', subcategories: [] }, { displayName: 'Komercyjne', urlName: 'komercyjne', subcategories: [] }] }, { displayName: 'Najem/dzierżawa', urlName: 'najem-dzierzawa', subcategories: [{ displayName: 'Dom', urlName: 'dom', subcategories: [] }, { displayName: 'Mieszkanie', urlName: 'mieszkanie', subcategories: [] }, { displayName: 'Prywatny/komercyjny', urlName: 'prywatny-komercyjny', subcategories: [] }, { displayName: 'Działka', urlName: 'dzialka', subcategories: [] }, { displayName: 'Budynki', urlName: 'budynki', subcategories: [] }] }, { displayName: 'Podatki', urlName: 'podatki', subcategories: [] }, { displayName: 'Prawo budowlane', urlName: 'prawo-budowlane', subcategories: [] }, { displayName: 'Dziedziczenie', urlName: 'dziedziczenie', subcategories: [] }, { displayName: 'Wzory dokumentów', urlName: 'wzory-dokumentow', subcategories: [] }] }, { displayName: 'Finanse', urlName: 'finanse', subcategories: [{ displayName: 'Kredyty', urlName: 'kredyty', subcategories: [] }, { displayName: 'Ubezpieczenia', urlName: 'ubezpieczenia', subcategories: [] }, { displayName: 'Kalkulatory', urlName: 'kalkulatory', subcategories: [] }, { displayName: 'Inwestycje', urlName: 'inwestycje', subcategories: [] }, { displayName: 'Dofinansowanie i dotacje', urlName: 'dofinansowanie-i-dotacje', subcategories: [] }] }, { displayName: 'Porady i inspiracje', urlName: 'porady-i-inspiracje', subcategories: [{ displayName: 'Budowa i remont', urlName: 'budowa-i-remont', subcategories: [] }, { displayName: 'Użytkowanie', urlName: 'uzytkowanie', subcategories: [] }, { displayName: 'Balkon i ogród', urlName: 'balkon-i-ogrod', subcategories: [] }, { displayName: 'Aranżacje', urlName: 'aranzacje', subcategories: [] }, { displayName: 'Design', urlName: 'design', subcategories: [] }] }, { displayName: 'Eksperci', urlName: 'eksperci', subcategories: [{ displayName: 'Felietony', urlName: 'felietony', subcategories: [] }, { displayName: 'Zapytaj eksperta', urlName: 'zapytaj-eksperta', subcategories: [] }, { displayName: 'Materiały źródłowe', urlName: 'materialy-zrodlowe', subcategories: [] }] }],
    getPath = prefix => ({ urlName, subcategories }) =>
        (path => [path, ...subcategories.flatMap(getPath(path))])
        (prefix + (prefix && '/') + urlName),
    paths = items.flatMap(getPath(''));

console.log(paths);
.as-console-wrapper { max-height: 100% !important; top: 0; }

You can try this: Loop through your items, the inside collect the children, return the first parent item without the slash and the children together

const items = [{
  displayName: 'Wiadomości',
  urlName: 'wiadomosci',
  subcategories: [{
    displayName: 'Newsy',
    urlName: 'newsy',
    subcategories: []
  }, {
    displayName: 'Wydarzenia',
    urlName: 'wydarzenia',
    subcategories: []
  }, {
    displayName: 'Komentarze i analizy',
    urlName: 'komentarze-i-analizy',
    subcategories: []
  }, {
    displayName: 'Reportaże',
    urlName: 'reportaze',
    subcategories: []
  }]
}, {
  displayName: 'Prawo',
  urlName: 'prawo',
  subcategories: [{
    displayName: 'Sprzedaż/zakup',
    urlName: 'sprzedaz-zakup',
    subcategories: [{
      displayName: 'Dom',
      urlName: 'dom',
      subcategories: []
    }, {
      displayName: 'Mieszkanie',
      urlName: 'mieszkanie',
      subcategories: []
    }, {
      displayName: 'Działka',
      urlName: 'dzialka',
      subcategories: []
    }, {
      displayName: 'Komercyjne',
      urlName: 'komercyjne',
      subcategories: []
    }]
  }, {
    displayName: 'Najem/dzierżawa',
    urlName: 'najem-dzierzawa',
    subcategories: [{
      displayName: 'Dom',
      urlName: 'dom',
      subcategories: []
    }, {
      displayName: 'Mieszkanie',
      urlName: 'mieszkanie',
      subcategories: []
    }, {
      displayName: 'Prywatny/komercyjny',
      urlName: 'prywatny-komercyjny',
      subcategories: []
    }, {
      displayName: 'Działka',
      urlName: 'dzialka',
      subcategories: []
    }, {
      displayName: 'Budynki',
      urlName: 'budynki',
      subcategories: []
    }]
  }, {
    displayName: 'Podatki',
    urlName: 'podatki',
    subcategories: []
  }, {
    displayName: 'Prawo budowlane',
    urlName: 'prawo-budowlane',
    subcategories: []
  }, {
    displayName: 'Dziedziczenie',
    urlName: 'dziedziczenie',
    subcategories: []
  }, {
    displayName: 'Wzory dokumentów',
    urlName: 'wzory-dokumentow',
    subcategories: []
  }]
}, {
  displayName: 'Finanse',
  urlName: 'finanse',
  subcategories: [{
    displayName: 'Kredyty',
    urlName: 'kredyty',
    subcategories: []
  }, {
    displayName: 'Ubezpieczenia',
    urlName: 'ubezpieczenia',
    subcategories: []
  }, {
    displayName: 'Kalkulatory',
    urlName: 'kalkulatory',
    subcategories: []
  }, {
    displayName: 'Inwestycje',
    urlName: 'inwestycje',
    subcategories: []
  }, {
    displayName: 'Dofinansowanie i dotacje',
    urlName: 'dofinansowanie-i-dotacje',
    subcategories: []
  }]
}, {
  displayName: 'Porady i inspiracje',
  urlName: 'porady-i-inspiracje',
  subcategories: [{
    displayName: 'Budowa i remont',
    urlName: 'budowa-i-remont',
    subcategories: []
  }, {
    displayName: 'Użytkowanie',
    urlName: 'uzytkowanie',
    subcategories: []
  }, {
    displayName: 'Balkon i ogród',
    urlName: 'balkon-i-ogrod',
    subcategories: []
  }, {
    displayName: 'Aranżacje',
    urlName: 'aranzacje',
    subcategories: []
  }, {
    displayName: 'Design',
    urlName: 'design',
    subcategories: []
  }]
}, {
  displayName: 'Eksperci',
  urlName: 'eksperci',
  subcategories: [{
    displayName: 'Felietony',
    urlName: 'felietony',
    subcategories: []
  }, {
    displayName: 'Zapytaj eksperta',
    urlName: 'zapytaj-eksperta',
    subcategories: []
  }, {
    displayName: 'Materiały źródłowe',
    urlName: 'materialy-zrodlowe',
    subcategories: []
  }]
}];


const result = items.reduce((acc, x) => {
  list = x.subcategories.reduce((acc2, y) => {
    acc2.push(x.displayName.toLowerCase() + '/' + y.urlName.toLowerCase())
    return acc2
  }, []);
  acc.push([x.displayName.toLowerCase(), ...list]);
  return acc;
}, []).flat()
console.log(result)

Related