Je travaille sur ce défi depuis FreeCodeCamp

Aplatissez un tableau imbriqué. Vous devez tenir compte des différents niveaux d'imbrication.

J'essaie de le résoudre en utilisant la récursivité.

Voici mon code:

function steamroller(arr) {
    var flatArray = [];

    function flatten(obj) {
        if (!Array.isArray(obj)) {
            return(obj);
        }
        for (var i in obj) {
            return flatten(obj[i]);
        }
    }

    flatArray.push(flatten(arr));

    console.log(flatArray);
}

steamroller([1, [2], [3, [[4]]]]);

Cela enregistre:

Array [ 1 ]

Je peux voir le problème, l'instruction return rompt la boucle for, donc seule la première valeur est retournée.

Cependant, si je laisse le retour et utilise simplement:

flatten(obj[i]);

Je reviens:

Array [ undefined ]

Que dois-je faire pour résoudre ce problème?

0
John Behan 23 juil. 2015 à 07:11

4 réponses

Meilleure réponse

J'ai modifié votre code pour qu'il fonctionne, en ajoutant des commentaires:

function steamroller(arr) {
var flatArray = [];

function flatten(obj) {
    if (!Array.isArray(obj)) {
        // We got to the innermost element. Push it to the array.
        flatArray.push(obj); 
        return;
    }
    for (i = 0; i < obj.length; i++) {
        flatten(obj[i]); // Do not return here.
    }
}

flatten(arr);

console.log(flatArray);
}

steamroller([1, [2], [3, [[4]]]]);
2
Nina Satragno 23 juil. 2015 à 04:27

Voici une approche légèrement différente:

function flat(a,f){
 if (!f) var f=[];
 a.forEach(function(e){
  if (Array.isArray(e)) flat(e,f);
  else f.push(e);
 });
 return f;
}

var flatArray=flat(deepArray);

La fonction renvoie le tableau aplati à chaque fois mais ignore sa valeur de retour dans les appels internes d'elle-même (flat(e,f)). Au lieu de cela, il continue à pousser chaque valeur non Array vers le même f - Array qui a été défini initialement dans l'appel externe de flat(a).

En utilisant le deuxième argument (généralement inutilisé), vous pouvez également concaténer des valeurs à un tableau plat déjà existant comme

var a=[[2,4,[5,6,[7,8],[9,10]],1],3];
var fl1=flat(a);
// "2|4|5|6|7|8|9|10|1|3"
var fl2=flat(a,fl1);
// "2|4|5|6|7|8|9|10|1|3|2|4|5|6|7|8|9|10|1|3"
1
cars10m 23 juil. 2015 à 05:44

Une solution entièrement récursive , si vous n'avez pas besoin de conserver le tableau d'origine intact:

function flatten (obj, memo) {
    memo = (memo || []);
    if (Array.isArray(obj)) {
        if (obj.length) {
            // flatten the first element, removing it from the original array
            flatten(obj.shift(), memo);
            // flatten the rest of the original array
            flatten(obj, memo);
        }
        return memo;
    }
    return memo.push(obj);
}

Nous vérifions tout d'abord si obj est un tableau. Ensuite, s'il n'est pas vide, aplatissez le premier élément, aplatissez le reste. Si l'objet n'est pas un tableau, il est renvoyé et poussé dans le tableau memo, qui est renvoyé.

Notez que dans la première ligne, je mets memo = (memo || []). Cela garantit que nous obtenons toujours un nouveau tableau lors du premier appel, si memo n'est pas défini.

1
ThiagoSckianta 12 mars 2016 à 05:32

Vous devez ajouter les éléments au tableau de résultats.

function flatten(arr){
  var flat = [];

  arr.forEach(function(item){     
    flat.push.apply(flat, Array.isArray(item) ? flatten(item) : [item]);      
  });

  return flat;
}
2
CD.. 23 juil. 2015 à 04:24