6
votes

condensation de l'objet Array récursivement en JavaScript

J'ai une gamme d'objets dans le format ci-dessous:

{
  "country": "India",
  "children": [
    {
      "name": "Karnataka",
      "type": "State",
      "children": [
        {
          "name": "Bangalore",
          "type": "city"
        },
        {
          "name": "Mangalore",
          "type": "city"
        }
      ]
    },
    {
      "name": "Kerala",
      "type": "State",
      "children": [
      ]
    },
    {
      "name": "Maharastra",
      "type": "State",
      "children": [
        {
          "name": "Mumbai",
          "type": "city"
        },
        {
          "name": "Pune",
          "type": "city"
        }
      ]
    }
  ]
}


3 commentaires

@ Rayondabre-me semble-t-il réducteur et supprimer des membres non désirés est meilleur, mais le soulignez-vous. Sinon, il y a la construction intégrée.


Cette question de questions pourrait vous aider


Je ne sais pas à quel point il est important que vous préserviez l'objet de données d'origine, mais si vous allez des fonctions de tableau, vous le perdrez probablement que si vous clonez l'objet en premier lieu par certains moyens.


6 Réponses :


1
votes

Essayez ceci:

function condense(arr) {

  arr.children = arr.children.map(function(c) {
    c.children = c.children.filter(function(c1) {
      return c1.name;
    });
    return c;
  });

  return arr;
}


2 commentaires

J'ai essayé une approche similaire. Je voulais tenter cela avec une récursion.


Pourquoi ? Vous n'avez que deux niveaux de profondeur. De plus, au premier niveau, vous gardez des enfants vides, sur le second que vous les supprimez. Cela ne semble pas être un bon candidat à la récursivité.



1
votes

pas au fait em> avec des sous-traitants.js. Vous pouvez faire cela avec ES5 réducteur em> et supprimer des membres que vous ne voulez pas, il devrait être plus efficace que d'autres approches. La récursion utilise la récursivité (qui n'est pas aussi efficace que la transformation en série, mais est probablement moins de code), vous pouvez donc nier les objets aussi profonds que vous le souhaitez:

p>

function removeEmpty(obj) {
  obj.children.reduceRight(function (acc, child, i) {
    if (!child.name) {
      obj.children.splice(i, 1);
    } else if (child.children) {
      removeEmpty(child);
    }
    return null;
  }, null);
  return obj;
}

// Test
var data = {
  "country": "India",
  "children": [
    {
      "name": "Karnataka",
      "type": "State",
      "children": [
        {
          "name": "",
          "type": "city"
        },
        {
          "name": "Bangalore",
          "type": "city"
        },
        {
          "name": "Mangalore",
          "type": "city"
        }
      ]
    },
    {
      "name": "Kerala",
      "type": "State",
      "children": [
        {
          "name": "",
          "type": "city"
        }
      ]
    },
    {
      "name": "Maharashtra",
      "type": "State",
      "children": [
        {
          "name": "Mumbai",
          "type": "city"
        },
        {
          "name": "Pune",
          "type": "city"
        }
      ]
    }
  ]
}


document.write('Original:<br>' + JSON.stringify(data) + '<br><br>' +
               'Modified:<br>' + JSON.stringify(removeEmpty(data)));


3 commentaires

Oh, l'utilisation de réducteur est tellement déroutante ici, car vous ne réduisez rien ...


Oui, c'est juste pour itérer de longueur à 0, l'accumulateur est ignoré. Peut-être qu'il devrait y avoir un forachight ? ;-) En y pensant maintenant, le retour null peut être omis.


Peut-être aussi _ au lieu de acc



3
votes

Ceci est une solution récursive avec Array # filtre () code> .

function filterName(a) {
    if (a.name) {
        if (Array.isArray(a.children)) {
            a.children = a.children.filter(filterName);
        }
        return true;
    }
}

var object = { "country": "India", "children": [{ "name": "Karnataka", "type": "State", "children": [{ "name": "", "type": "city" }, { "name": "Bangalore", "type": "city" }, { "name": "Mangalore", "type": "city" }] }, { "name": "Kerala", "type": "State", "children": [{ "name": "", "type": "city" }] }, { "name": "Maharashtra", "type": "State", "children": [{ "name": "Mumbai", "type": "city" }, { "name": "Pune", "type": "city" }] }] };

object.children.forEach(filterName);
document.write("<pre>" + JSON.stringify(object, 0, 4) + "</pre>");


0 commentaires

1
votes

Ceci est très spécifique à votre exemple.

Lien vers Fiddle P>

P>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>


0 commentaires

1
votes

Probablement pas le moyen le plus court, mais cela fonctionne:

obj.children = _.each(obj.children, filter);

function filter(child, index, arr) {
  if (child && child.name === '') {
    // remove the ones without name
    arr.splice(index, 1);

  } else if (_.has(child, 'children')) {
    // remove nested children
    child.children = _.each(child.children, filter);

    // check for empty children array and remove it (if needed)
    /*
    if (child.children.length === 0) {
      delete child['children'];
    }
    */
  }

  return child;
}


0 commentaires

1
votes

Je sais qu'une approche récursive est posée, mais je ne peux pas m'empêcher de donner une seule doublure ici.

var newData = JSON.parse(JSON.stringify(data).replace(/{"name":"".+?},?/g, ""));


0 commentaires