recursión recursivos recursividad recursivas recursiva react que paginas funcion ejemplos ejemplo calculos javascript recursion javascript-objects lodash

javascript - recursivos - recursividad react



Objeto de aplanamiento profundo de JavaScript de forma recursiva (11)

Aquí está la solución que usa la función recursiva que llamé flattenNestedObjectsArray() (para JavaScript nativo ):

function flattenNestedObjectsArray(arr, part){ var flattened = part || [], items; arr.forEach(function(v){ if (Array.isArray(v.items) && v.items.length) { items = v.items; v.items = []; flattened.push(v); flattened.concat(flattened, flattenNestedObjectsArray(items, flattened)); } else { flattened.push(v); } }); return flattened; } var flattened = flattenNestedObjectsArray(data); console.log(JSON.stringify(flattened, 0, 4));

La salida de console.log :

[ { "id": 1, "level": "1", "text": "Sammy", "type": "Item", "items": [] }, { "id": 11, "level": "2", "text": "Table", "type": "Item", "items": [] }, { "id": 111, "level": "3", "text": "Dog", "type": "Item", "items": null }, { "id": 112, "level": "3", "text": "Cat", "type": "Item", "items": null }, { "id": 12, "level": "2", "text": "Chair", "type": "Item", "items": [] }, { "id": 121, "level": "3", "text": "Dog", "type": "Item", "items": null }, { "id": 122, "level": "3", "text": "Cat", "type": "Item", "items": null }, { "id": 2, "level": "1", "text": "Sundy", "type": "Item", "items": [] }, { "id": 21, "level": "2", "text": "MTable", "type": "Item", "items": [] }, { "id": 211, "level": "3", "text": "MTDog", "type": "Item", "items": null }, { "id": 212, "level": "3", "text": "MTCat", "type": "Item", "items": null }, { "id": 22, "level": "2", "text": "MChair", "type": "Item", "items": [] }, { "id": 221, "level": "3", "text": "MCDog", "type": "Item", "items": null }, { "id": 222, "level": "3", "text": "MCCat", "type": "Item", "items": null }, { "id": 3, "level": "1", "text": "Bruce", "type": "Folder", "items": [] }, { "id": 31, "level": "2", "text": "BTable", "type": "Item", "items": [] }, { "id": 311, "level": "3", "text": "BTDog", "type": "Item", "items": null }, { "id": 312, "level": "3", "text": "BTCat", "type": "Item", "items": null }, { "id": 32, "level": "2", "text": "Chair", "type": "Item", "items": [] }, { "id": 321, "level": "3", "text": "BCDog", "type": "Item", "items": null }, { "id": 322, "level": "3", "text": "BCCat", "type": "Item", "items": null } ]

Datos :

var data = [ { "id": 1, "level": "1", "text": "Sammy", "type": "Item", "items": [ { "id": 11, "level": "2", "text": "Table", "type": "Item", "items": [ { "id": 111, "level": "3", "text": "Dog", "type": "Item", "items": null }, { "id": 112, "level": "3", "text": "Cat", "type": "Item", "items": null } ] }, { "id": 12, "level": "2", "text": "Chair", "type": "Item", "items": [ { "id": 121, "level": "3", "text": "Dog", "type": "Item", "items": null }, { "id": 122, "level": "3", "text": "Cat", "type": "Item", "items": null } ] } ] }, { "id": 2, "level": "1", "text": "Sundy", "type": "Item", "items": [ { "id": 21, "level": "2", "text": "MTable", "type": "Item", "items": [ { "id": 211, "level": "3", "text": "MTDog", "type": "Item", "items": null }, { "id": 212, "level": "3", "text": "MTCat", "type": "Item", "items": null } ] }, { "id": 22, "level": "2", "text": "MChair", "type": "Item", "items": [ { "id": 221, "level": "3", "text": "MCDog", "type": "Item", "items": null }, { "id": 222, "level": "3", "text": "MCCat", "type": "Item", "items": null } ] } ] }, { "id": 3, "level": "1", "text": "Bruce", "type": "Folder", "items": [ { "id": 31, "level": "2", "text": "BTable", "type": "Item", "items": [ { "id": 311, "level": "3", "text": "BTDog", "type": "Item", "items": null }, { "id": 312, "level": "3", "text": "BTCat", "type": "Item", "items": null } ] }, { "id": 32, "level": "2", "text": "Chair", "type": "Item", "items": [ { "id": 321, "level": "3", "text": "BCDog", "type": "Item", "items": null }, { "id": 322, "level": "3", "text": "BCCat", "type": "Item", "items": null } ] } ] } ];

Código :

var fdr = []; var fd = function(n) { if (n.items) { _.forEach(n.items, function (value){ fd(value); }); } fdr.push(n); }; _.forEach(data, fd); console.log(fdr);

Salida deseada :

var data = [ { "id": 1, "level": "1", "text": "Sammy", "type": "Item", "items": [] }, { "id": 11, "level": "2", "text": "Table", "type": "Item", "items": [] }, { "id": 111, "level": "3", "text": "Dog", "type": "Item", "items": null }, { "id": 112, "level": "3", "text": "Cat", "type": "Item", "items": null }, { "id": 12, "level": "2", "text": "Chair", "type": "Item", "items": [] }, { "id": 121, "level": "3", "text": "Dog", "type": "Item", "items": null }, { "id": 122, "level": "3", "text": "Cat", "type": "Item", "items": null }, { "id": 2, "level": "1", "text": "Sundy", "type": "Item", "items": [] }, { "id": 21, "level": "2", "text": "MTable", "type": "Item", "items": [] }, { "id": 211, "level": "3", "text": "MTDog", "type": "Item", "items": null }, { "id": 212, "level": "3", "text": "MTCat", "type": "Item", "items": null }, { "id": 22, "level": "2", "text": "MChair", "type": "Item", "items": [] }, { "id": 221, "level": "3", "text": "MCDog", "type": "Item", "items": null }, { "id": 222, "level": "3", "text": "MCCat", "type": "Item", "items": null }, { "id": 3, "level": "1", "text": "Bruce", "type": "Folder", "items": [] }, { "id": 31, "level": "2", "text": "BTable", "type": "Item", "items": [] }, { "id": 311, "level": "3", "text": "BTDog", "type": "Item", "items": null }, { "id": 312, "level": "3", "text": "BTCat", "type": "Item", "items": null }, { "id": 32, "level": "2", "text": "Chair", "type": "Item", "items": [] }, { "id": 321, "level": "3", "text": "BCDog", "type": "Item", "items": null }, { "id": 322, "level": "3", "text": "BCCat", "type": "Item", "items": null } ];

Condiciones :

  • Objeto tiene nivel de incógnitas. Algunos item secundarios pueden tener un nivel hacia abajo y otros hasta 5.

Preguntas

La función fd en el código es lo que he encontrado. Creo que hay una manera "más limpia" de hacer esto, simplemente no puedo pensar en algo. Además, la función devuelve items objeto, lo hace objeto circular.

JsBin: http://jsbin.com/debojiqove/2/edit?html,js,output

¿Hay una manera de aplanar el objeto recursivamente con lodash o simplemente JavaScript?


Aquí está mi versión de la función recursiva flattenItems. Tenga en cuenta que he eliminado la propiedad de los elementos en todos los niveles en el resultado final.

function flattenItems(data) { // flat is the array that we will return by the end var flat = []; data.forEach(function(item) { // get child properties only var flatItem = {}; Object.keys(item).forEach(function(key) { if(item[key] && item.hasOwnProperty(key) && !Array.isArray(item[key])) { flatItem[key] = item[key]; } // recursive flattern on subitems // add recursive call results to the // current stack version of "flat", by merging arrays else if(Array.isArray(item[key])) { Array.prototype.push.apply(flat, flattenItems(item[key])); } }); flat.push(flatItem); }); // sort by level before returning return flat.sort(function(i1, i2) { return parseInt(i1.level) - parseInt(i2.level); }); }

Aquí hay un fiddle usando sus datos de muestra, verifique la consola.


Con un poco de sabor ES6.

function flatten(xs) { return xs.reduce((acc, x) => { acc = acc.concat(x); if (x.items) { acc = acc.concat(flatten(x.items)); x.items = []; } return acc; }, []); }


Desde Lo-Dash 3.0.0, _.flattenDeep (datos) devolverá una matriz profundamente aplanada como desee. También hay una función _.flatten (datos) que se aplana poco a poco.


JavaScript simple

var data = [{ "id": 1, "level": "1", "text": "Sammy", "type": "Item", "items": [{ "id": 11, "level": "2", "text": "Table", "type": "Item", "items": [{ "id": 111, "level": "3", "text": "Dog", "type": "Item", "items": null }, { "id": 112, "level": "3", "text": "Cat", "type": "Item", "items": null }] }, { "id": 12, "level": "2", "text": "Chair", "type": "Item", "items": [{ "id": 121, "level": "3", "text": "Dog", "type": "Item", "items": null }, { "id": 122, "level": "3", "text": "Cat", "type": "Item", "items": null }] }] }, { "id": 2, "level": "1", "text": "Sundy", "type": "Item", "items": [{ "id": 21, "level": "2", "text": "MTable", "type": "Item", "items": [{ "id": 211, "level": "3", "text": "MTDog", "type": "Item", "items": null }, { "id": 212, "level": "3", "text": "MTCat", "type": "Item", "items": null }] }, { "id": 22, "level": "2", "text": "MChair", "type": "Item", "items": [{ "id": 221, "level": "3", "text": "MCDog", "type": "Item", "items": null }, { "id": 222, "level": "3", "text": "MCCat", "type": "Item", "items": null }] }] }, { "id": 3, "level": "1", "text": "Bruce", "type": "Folder", "items": [{ "id": 31, "level": "2", "text": "BTable", "type": "Item", "items": [{ "id": 311, "level": "3", "text": "BTDog", "type": "Item", "items": null }, { "id": 312, "level": "3", "text": "BTCat", "type": "Item", "items": null }] }, { "id": 32, "level": "2", "text": "Chair", "type": "Item", "items": [{ "id": 321, "level": "3", "text": "BCDog", "type": "Item", "items": null }, { "id": 322, "level": "3", "text": "BCCat", "type": "Item", "items": null }] }] }]; var r = []; function flatten(a) { if (a.length == 0) return; var o = {}; o.id = a[0].id; o.level = a[0].level; o.text = a[0].text; o.type = a[0].type o.items = a[0].items == null ? null : [] r.push(o); if (Array.isArray(a[0].items)) { flatten(a[0].items); } a.shift(); flatten(a); } flatten(data); document.write(''<pre>'' + JSON.stringify(r, 0, 2) + ''</pre>'');


Necesitaba hacer lo mismo, y mientras resolvía mi problema, encontraba una solución para el tuyo usando lodash:

function kids(node) { return node.items ? [{...node, items: []}, _.map(node.items, kids)] : {...node, items: null}; } _.flatMapDeep(data, kids);


Otra forma con función reductora recursiva.

_.reduce(data, function reducer(result, val) { var items = _.reduce(val.items, reducer, []); val.items = _.isArray(val.items) ? [] : val.items; return _.concat(result, val, items); }, []);


Respuesta de Роман Парадеев modificada para hacerla un poco más dinámica.

function flatten(xs, childSelector) { return xs.reduce((acc, x) => { acc = acc.concat(x); let children = childSelector(x); if (children) { acc = acc.concat(flatten(children, childSelector)); } return acc; }, []); }

Ahora los items no están codificados, y puede usarlos flatten(data, x => x.items) .


Solo una sola función de línea puede hacer este trabajo.

var data = [{ "id": 1, "level": "1", "text": "Sammy", "type": "Item", "items": [{ "id": 11, "level": "2", "text": "Table", "type": "Item", "items": [{ "id": 111, "level": "3", "text": "Dog", "type": "Item", "items": null }, { "id": 112, "level": "3", "text": "Cat", "type": "Item", "items": null }] }, { "id": 12, "level": "2", "text": "Chair", "type": "Item", "items": [{ "id": 121, "level": "3", "text": "Dog", "type": "Item", "items": null }, { "id": 122, "level": "3", "text": "Cat", "type": "Item", "items": null }] }] }, { "id": 2, "level": "1", "text": "Sundy", "type": "Item", "items": [{ "id": 21, "level": "2", "text": "MTable", "type": "Item", "items": [{ "id": 211, "level": "3", "text": "MTDog", "type": "Item", "items": null }, { "id": 212, "level": "3", "text": "MTCat", "type": "Item", "items": null }] }, { "id": 22, "level": "2", "text": "MChair", "type": "Item", "items": [{ "id": 221, "level": "3", "text": "MCDog", "type": "Item", "items": null }, { "id": 222, "level": "3", "text": "MCCat", "type": "Item", "items": null }] }] }, { "id": 3, "level": "1", "text": "Bruce", "type": "Folder", "items": [{ "id": 31, "level": "2", "text": "BTable", "type": "Item", "items": [{ "id": 311, "level": "3", "text": "BTDog", "type": "Item", "items": null }, { "id": 312, "level": "3", "text": "BTCat", "type": "Item", "items": null }] }, { "id": 32, "level": "2", "text": "Chair", "type": "Item", "items": [{ "id": 321, "level": "3", "text": "BCDog", "type": "Item", "items": null }, { "id": 322, "level": "3", "text": "BCCat", "type": "Item", "items": null }] }] }], flatIron = (a,b) => a.reduce((p,c) => {!!c.items ? (p.push(c), flatIron(c.items,p), c.items = []) : p.push(c); return p},b), flatArr = flatIron(data,[]); document.write(''<pre>'' + JSON.stringify(flatArr, 0, 2) + ''</pre>'');


Una solución en Javascript simple con respecto a los elementos. No mutila la matriz fuente.

function flat(r, a) { var b = {}; Object.keys(a).forEach(function (k) { if (k !== ''items'') { b[k] = a[k]; } }); r.push(b); if (Array.isArray(a.items)) { b.items = a.items.map(function (a) { return a.id; }); return a.items.reduce(flat, r); } return r; } var data = [{ "id": 1, "level": "1", "text": "Sammy", "type": "Item", "items": [{ "id": 11, "level": "2", "text": "Table", "type": "Item", "items": [{ "id": 111, "level": "3", "text": "Dog", "type": "Item", "items": null }, { "id": 112, "level": "3", "text": "Cat", "type": "Item", "items": null }] }, { "id": 12, "level": "2", "text": "Chair", "type": "Item", "items": [{ "id": 121, "level": "3", "text": "Dog", "type": "Item", "items": null }, { "id": 122, "level": "3", "text": "Cat", "type": "Item", "items": null }] }] }, { "id": 2, "level": "1", "text": "Sundy", "type": "Item", "items": [{ "id": 21, "level": "2", "text": "MTable", "type": "Item", "items": [{ "id": 211, "level": "3", "text": "MTDog", "type": "Item", "items": null }, { "id": 212, "level": "3", "text": "MTCat", "type": "Item", "items": null }] }, { "id": 22, "level": "2", "text": "MChair", "type": "Item", "items": [{ "id": 221, "level": "3", "text": "MCDog", "type": "Item", "items": null }, { "id": 222, "level": "3", "text": "MCCat", "type": "Item", "items": null }] }] }, { "id": 3, "level": "1", "text": "Bruce", "type": "Folder", "items": [{ "id": 31, "level": "2", "text": "BTable", "type": "Item", "items": [{ "id": 311, "level": "3", "text": "BTDog", "type": "Item", "items": null }, { "id": 312, "level": "3", "text": "BTCat", "type": "Item", "items": null }] }, { "id": 32, "level": "2", "text": "Chair", "type": "Item", "items": [{ "id": 321, "level": "3", "text": "BCDog", "type": "Item", "items": null }, { "id": 322, "level": "3", "text": "BCCat", "type": "Item", "items": null }] }] }]; document.write(''<pre>'' + JSON.stringify(data.reduce(flat, []), 0, 4) + ''</pre>'');


Una solución más corta utilizando reduce y recursion

function flatten(data){ return data.reduce(function(result,next){ result.push(next); if(next.items){ result = result.concat(flatten(next.items)); next.items = []; } return result; },[]); } var data = [ { "id": 1, "level": "1", "text": "Sammy", "type": "Item", "items": [ { "id": 11, "level": "2", "text": "Table", "type": "Item", "items": [ { "id": 111, "level": "3", "text": "Dog", "type": "Item", "items": null }, { "id": 112, "level": "3", "text": "Cat", "type": "Item", "items": null } ] }, { "id": 12, "level": "2", "text": "Chair", "type": "Item", "items": [ { "id": 121, "level": "3", "text": "Dog", "type": "Item", "items": null }, { "id": 122, "level": "3", "text": "Cat", "type": "Item", "items": null } ] } ] }, { "id": 2, "level": "1", "text": "Sundy", "type": "Item", "items": [ { "id": 21, "level": "2", "text": "MTable", "type": "Item", "items": [ { "id": 211, "level": "3", "text": "MTDog", "type": "Item", "items": null }, { "id": 212, "level": "3", "text": "MTCat", "type": "Item", "items": null } ] }, { "id": 22, "level": "2", "text": "MChair", "type": "Item", "items": [ { "id": 221, "level": "3", "text": "MCDog", "type": "Item", "items": null }, { "id": 222, "level": "3", "text": "MCCat", "type": "Item", "items": null } ] } ] }, { "id": 3, "level": "1", "text": "Bruce", "type": "Folder", "items": [ { "id": 31, "level": "2", "text": "BTable", "type": "Item", "items": [ { "id": 311, "level": "3", "text": "BTDog", "type": "Item", "items": null }, { "id": 312, "level": "3", "text": "BTCat", "type": "Item", "items": null } ] }, { "id": 32, "level": "2", "text": "Chair", "type": "Item", "items": [ { "id": 321, "level": "3", "text": "BCDog", "type": "Item", "items": null }, { "id": 322, "level": "3", "text": "BCCat", "type": "Item", "items": null } ] } ] } ]; var result = flatten(data); document.write(''<pre>'' + JSON.stringify(result, 0, 4) + ''</pre>'');