Smith john
Smith john

Reputation: 3

Looping in a multidimensionnal array dynamically and flatten object inside it

everybody. I will need to browse an array dynamically and flatten the objects it contains, knowing that it may evolve and contain an extra dimension.

for example the table contains this

const myArray = [
         {
           key: "CED", 
           label: "CEDRIC", 
           sub : null
         },
         {
           key: "AR", 
           label: "ARNAUD", 
           sub : [
                  {
                   key: "LUC", 
                   label: "LUCAS", 
                   sub : null
                  }
                 ]
         },
         {
           key: "PET", 
           label: "PETER", 
           sub : [
                  {
                   key: "JO", 
                   label: "JOHN", 
                   sub : null
                  },
                  {
                   key: "LUD", 
                   label: "LUDO", 
                   sub : [
                          {
                           key: "THO", 
                           label: "THOMAS", 
                           sub : null
                          }
                         ]
                  }
                 ]
         },
         {
           key: "TER", 
           label: "TERRY", 
           sub : null
         }
      ]

the expected output is

[
 {key: "CED", label: "CEDRIC"},
 {key: "AR", label: "ARNAUD"}, 
 {key: "LUC", label: "LUCAS"},
 {key: "PET", label: "PETER"},
 {key: "JO", label: "JOHN"},
 {key: "LUD", label: "LUDO"},
 {key: "THO", label: "THOMAS"},
 {key: "TER", label: "TERRY"}
]

I tried with a map, forEach, reduce etc but i also have to manually go down in the tree.

  const test = myArray.reduce((accumulator, value) => {
    return []
      .concat(
        accumulator,
        value,
        value.sub && value.sub?.reduce((acc, val) => [].concat(acc, val))
      ).filter((val) => val !== null);
  }); // Output only the first and 2 level

would anyone have a way to do it dynamically without me having to worry about how many sub-dimensions there are?

Thank you in advance

Upvotes: 0

Views: 49

Answers (4)

Andrew Arthur
Andrew Arthur

Reputation: 1603

You can use recursion:

function traverse(item) {
    if (item.key) 
        output.push({ key: item.key, label: item.label });  
    if (!item.sub)
        return;
    for (var x of item.sub) {
        traverse(x);
    }
}

const myArray = [
    {
        key: "CED",
        label: "CEDRIC",
        sub: null
    },
    {
        key: "AR",
        label: "ARNAUD",
        sub: [
            {
                key: "LUC",
                label: "LUCAS",
                sub: null
            }
        ]
    },
    {
        key: "PET",
        label: "PETER",
        sub: [
            {
                key: "JO",
                label: "JOHN",
                sub: null
            },
            {
                key: "LUD",
                label: "LUDO",
                sub: [
                    {
                        key: "THO",
                        label: "THOMAS",
                        sub: null
                    }
                ]
            }
        ]
    },
    {
        key: "TER",
        label: "TERRY",
        sub: null
    }
];

var output = [];
traverse({ sub: myArray });
console.log(output);

Upvotes: 0

Sascha A.
Sascha A.

Reputation: 4626

Go with foreach through your array and if there is a sub-array go recursivly ahead.

function flatMyArray(array) {
    let result = [];
    array.forEach(obj => {
        result.push({key: obj.key, label: obj.label});
        if (obj.sub) {
            result = result.concat(flatMyArray(obj.sub));
        }
    });
    return result;
}

const myArray = [
         {
           key: "CED", 
           label: "CEDRIC", 
           sub : null
         },
         {
           key: "AR", 
           label: "ARNAUD", 
           sub : [
                  {
                   key: "LUC", 
                   label: "LUCAS", 
                   sub : null
                  }
                 ]
         },
         {
           key: "PET", 
           label: "PETER", 
           sub : [
                  {
                   key: "JO", 
                   label: "JOHN", 
                   sub : null
                  },
                  {
                   key: "LUD", 
                   label: "LUDO", 
                   sub : [
                          {
                           key: "THO", 
                           label: "THOMAS", 
                           sub : null
                          }
                         ]
                  }
                 ]
         },
         {
           key: "TER", 
           label: "TERRY", 
           sub : null
         }
      ];
      
  console.log(flatMyArray(myArray));

Upvotes: 0

Yoshi
Yoshi

Reputation: 54659

You can use the following method:

const out = myArray.reduce(function next(r, {key, label, sub}) {
    return [...r, {key, label}, ...(null === sub ? [] : sub.reduce(next, []))];
}, []);

Note the named inline function. It will not pollute the global namespace, yet will still be usable inside the function, allowing for an easy way to recurse deeper.

const myArray = [
    {
        key: "CED",
        label: "CEDRIC",
        sub : null
    },
    {
        key: "AR",
        label: "ARNAUD",
        sub : [
            {
                key: "LUC",
                label: "LUCAS",
                sub : null
            }
        ]
    },
    {
        key: "PET",
        label: "PETER",
        sub : [
            {
                key: "JO",
                label: "JOHN",
                sub : null
            },
            {
                key: "LUD",
                label: "LUDO",
                sub : [
                    {
                        key: "THO",
                        label: "THOMAS",
                        sub : null
                    }
                ]
            }
        ]
    },
    {
        key: "TER",
        label: "TERRY",
        sub : null
    }
];

const out = myArray.reduce(function next(r, {key, label, sub}) {
    return [...r, {key, label}, ...(null === sub ? [] : sub.reduce(next, []))];
}, []);


console.log(out);

Upvotes: 1

keidakida
keidakida

Reputation: 741

You should use recursion to achieve this like shown:

const myArray = [{
            key: "CED",
            label: "CEDRIC",
            sub: null
        },
        {
            key: "AR",
            label: "ARNAUD",
            sub: [{
                key: "LUC",
                label: "LUCAS",
                sub: null
            }]
        },
        {
            key: "PET",
            label: "PETER",
            sub: [{
                    key: "JO",
                    label: "JOHN",
                    sub: null
                },
                {
                    key: "LUD",
                    label: "LUDO",
                    sub: [{
                        key: "THO",
                        label: "THOMAS",
                        sub: null
                    }]
                }
            ]
        },
        {
            key: "TER",
            label: "TERRY",
            sub: null
        }
    ]

    results = []

    function getPair(myArray) {
        myArray.map(item => {
            results.push({
                key: item.key,
                label: item.label
            })
            if (item.sub != null) {
                getPair(item.sub);
            }
        })
    }

    getPair(myArray);

    console.log(results);

Upvotes: 0

Related Questions