Search code examples
javascriptarraysflatten

Flatten array with multiple nested objects


I have an array like this and I want it to be flatted in order to generate an excel with it, but I can't get more than two levels of flat. This is my data:

[
   {
      "idClient":1,
      "clientName":"Client One",
      "numItems":72,
      "projects":[
         {
            "idProject":1,
            "projectName":"Project One",
            "numItems":72,
            "languages":[
               {
                  "sourceLanguage":26,
                  "sourceLanguageName":"Spanish",
                  "numItems":72,
                  "targets":[
                     {
                        "targetLanguage":74,
                        "targetLanguageName":"English",
                        "numItems":36,
                        "numItemsSold":30,
                     },
                     {
                        "targetLanguage":20,
                        "targetLanguageName":"French",
                        "numItems":36,
                        "numItemsSold":7,
                     }
                  ]
               }
            ]
         }
      ]
   },
      {
      "idClient":1,
      "clientName":"Client One",
      "numItems":50,
      "projects":[
         {
            "idProject":1,
            "projectName":"Project Two",
            "numItems":50,
            "languages":[
               {
                  "sourceLanguage":26,
                  "sourceLanguageName":"Spanish",
                  "numItems":50,
                  "targets":[
                     {
                        "targetLanguage":74,
                        "targetLanguageName":"English",
                        "numItems":30,
                        "numItemsSold":3,
                     },
                     {
                        "targetLanguage":20,
                        "targetLanguageName":"French",
                        "numItems":20,
                        "numItemsSold":7,
                     }
                  ]
               }
            ]
         }
      ]
   }
]

What I want is generate a simple string list, with one row per target, something similar to this:

[
  {"Client One", "Proyect One", "Spanish", "English", "36", "30" },
  {"Client One", "Proyect One", "Spanish", "French", "36", "7" },
  {"Client One", "Proyect Two", "Spanish", "English", "30", "3" },
  {"Client One", "Proyect Two", "Spanish", "English", "20", "7" },
]

Looking on the internet and on stackoverflow, I found some interesting functions, like this one, but i cannot go beyond the languages property:

const fn = arr =>
          arr.flatMap(({ projects, ...rest }) =>
            projects.map(o => ({
              ...rest,
              ...o,
            }))
          );

Any help would be apprecited. Thanks in advace


Solution

  • I think you will have to flatMap all the arrays above targets, like this:

    let data = [
       {
          "idClient":1,
          "clientName":"Client One",
          "numItems":72,
          "projects":[
             {
                "idProject":1,
                "projectName":"Project One",
                "numItems":72,
                "languages":[
                   {
                      "sourceLanguage":26,
                      "sourceLanguageName":"Spanish",
                      "numItems":72,
                      "targets":[
                         {
                            "targetLanguage":74,
                            "targetLanguageName":"English",
                            "numItems":36,
                            "numItemsSold":30,
                         },
                         {
                            "targetLanguage":20,
                            "targetLanguageName":"French",
                            "numItems":36,
                            "numItemsSold":7,
                         }
                      ]
                   }
                ]
             }
          ]
       },
          {
          "idClient":1,
          "clientName":"Client One",
          "numItems":50,
          "projects":[
             {
                "idProject":1,
                "projectName":"Project Two",
                "numItems":50,
                "languages":[
                   {
                      "sourceLanguage":26,
                      "sourceLanguageName":"Spanish",
                      "numItems":50,
                      "targets":[
                         {
                            "targetLanguage":74,
                            "targetLanguageName":"English",
                            "numItems":30,
                            "numItemsSold":3,
                         },
                         {
                            "targetLanguage":20,
                            "targetLanguageName":"French",
                            "numItems":20,
                            "numItemsSold":7,
                         }
                      ]
                   }
                ]
             }
          ]
       }
    ]
    
    const fn = arr =>
              arr.flatMap(({ projects, ...rest }) =>
                projects.flatMap(({languages, ...rest1}) => 
                  languages.flatMap(({targets, ...rest2}) => {
                    return targets.map(t => ({...t, ...rest, ...rest1, ...rest2}))
                  })
                )
              );
              
    data = fn(data);
    console.log(data);
    

    This will give you flattened key-value pairs.