values recorrer objetos objeto keys crear array agregar javascript arrays json javascript-objects

recorrer - Renombrar/re-mapear eficientemente las claves de objeto javascript/json dentro de la matriz de objetos



recorrer array de objetos javascript (7)

Aquí hay otra visión de la sugerencia del OP de usar map() para mayor claridad (no rendimiento).

var newItems = items.map(item => ({ name: item.title, id: item.uid }));

Esto utiliza las funciones de flecha de ES6 y las sintaxis de acceso directo que son posibles cuando solo se pasa un parámetro a la función y solo una declaración en el cuerpo de la función.

Dependiendo de su historial con expresiones lambda en varios idiomas, este formulario puede o no tener eco en usted.

Tenga cuidado al devolver un objeto literal en la sintaxis de acceso directo de la función de flecha como esta. ¡No olvide los paréntesis adicionales alrededor del objeto literal!

Tengo algunos datos JSON estructurados como tal. Asumamos que esto es intercambiable, a través de JSON.parse() :

[ { "title": "pineapple", "uid": "ab982d34c98f" }, { "title": "carrots", "uid": "6f12e6ba45ec" } ]

Necesito que se vea así, reasignando title a name y uid a id con el resultado:

[ { "name": "pineapple", "id": "ab982d34c98f" }, { "name": "carrots", "id": "6f12e6ba45ec" } ]

La forma más obvia de hacerlo es así:

str = ''[{"title": "pineapple","uid": "ab982d34c98f"},{"title": "carrots", "uid": "6f12e6ba45ec"}]''; var arr = JSON.parse(str); for (var i = 0; i<arr.length; i++) { arr[i].name = arr[i].title; arr[i].id = arr[i].uid; delete arr[i].title; delete arr[i].uid; }

str = ''[{"title": "pineapple","uid": "ab982d34c98f"},{"title": "carrots", "uid": "6f12e6ba45ec"}]''; var arr = JSON.parse(str); for (var i = 0; i<arr.length; i++) { arr[i].name = arr[i].title; arr[i].id = arr[i].uid; delete arr[i].title; delete arr[i].uid; } $(''body'').append("<pre>"+JSON.stringify(arr, undefined, 4)+"</pre>");

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

... o usando algo más complejo (aunque no más eficiente) como this .

Todo esto está bien y es excelente, pero ¿y si hubiera 200,000 objetos en la matriz? Esto es un montón de sobrecarga de procesamiento.

¿Hay una forma más eficiente de volver a asignar un nombre de clave? Posiblemente sin recorrer toda la gama de objetos? Si su método es más eficiente, proporcione pruebas / referencias.


Como ya mencioné en los comentarios, si puede hacer ciertas suposiciones sobre los valores de los objetos, podría usar una expresión regular para reemplazar las claves, por ejemplo:

str = str.replace(/"title":/g, ''"name":'');

No es tan "limpio", pero podría hacer el trabajo más rápido.

Si tiene que analizar el JSON de todos modos, un enfoque más estructurado sería JSON.parse() y podría evitar un pase adicional sobre la matriz. JSON.parse embargo, esto probablemente depende de cómo el motor implementa JSON.parse (tal vez JSON.parse toda la cadena y luego realicen una segunda pasada con la función revivedor, en cuyo caso no obtendrías ninguna ventaja).

var arr = JSON.parse(str, function(prop, value) { switch(prop) { case "title": this.name = value; return; case "uid": this.id = value; return; default: return value; } });

Puntos de referencia, utilizando el script Node.js a continuación para probar 3 veces:

1389822740739: Beginning regex rename test 1389822740761: Regex rename complete // 22ms, 22ms, 21ms 1389822740762: Beginning parse and remap in for loop test 1389822740831: For loop remap complete // 69ms, 68ms, 68ms 1389822740831: Beginning reviver function test 1389822740893: Reviver function complete // 62ms, 61ms, 60ms

Parece como si la expresión regular (en este caso) es la más eficiente, pero tenga cuidado al intentar analizar JSON con expresiones regulares .

Script de prueba, cargando 100,230 líneas del JSON de muestra del OP:

fs = require(''fs''); fs.readFile(''test.json'', ''utf8'', function (err, data) { if (err) { return console.log(err); } console.log(new Date().getTime() + ": Beginning regex rename test"); var str = data.replace(/"title":/g, ''"name":''); str = str.replace(/"uid":/g, ''"id":''); JSON.parse(str); console.log(new Date().getTime() + ": Regex rename complete"); console.log(new Date().getTime() + ": Beginning parse and remap in for loop test"); var arr = JSON.parse(data); for (var i = 0; i < arr.length; i++) { arr[i].name = arr[i].title; arr[i].id = arr[i].uid; delete arr[i].title; delete arr[i].uid; } console.log(new Date().getTime() + ": For loop remap complete"); console.log(new Date().getTime() + ": Beginning reviver function test"); var arr = JSON.parse(data, function (prop, value) { switch (prop) { case "title": this.name = value; return; case "uid": this.id = value; return; default: return value; } }); console.log(new Date().getTime() + ": Reviver function complete"); });


Hice esta pregunta hace mucho tiempo, y desde entonces, me he acostumbrado a usar Array.prototype.map() para hacer el trabajo, más por la estabilidad y la limpieza del código que por el rendimiento. Si bien ciertamente no es el más destacado, se ve genial:

var repl = orig.map(function(obj) { return { name: obj.title, id: obj.uid } })

Si necesita una función más flexible (y compatible con ES6), intente:

let replaceKeyInObjectArray = (a, r) => a.map(o => Object.keys(o).map((key) => ({ [r[key] || key] : o[key] }) ).reduce((a, b) => Object.assign({}, a, b)))

p.ej

const arr = [{ abc: 1, def: 40, xyz: 50 }, { abc: 1, def: 40, xyz: 50 }, { abc: 1, def: 40, xyz: 50 }] const replaceMap = { "abc": "yyj" } replaceKeyInObjectArray(arr, replaceMap) /* [ { "yyj": 1, "def": 40, "xyz": 50 }, { "yyj": 1, "def": 40, "xyz": 50 }, { "yyj": 1, "def": 40, "xyz": 50 } ] */


Puede usar un paquete npm llamado node-data-transform .

Tu información :

const data = [ { title: ''pineapple'', uid: ''ab982d34c98f'', }, { title: ''carrots'', uid: ''6f12e6ba45ec'', }, ];

Su mapeo:

const map = { item: { name: ''title'', id: ''uid'', }, };

Y usa el paquete:

const DataTransform = require("node-json-transform").DataTransform; const dataTransform = DataTransform(data, map); const result = dataTransform.transform(); console.log(result);

Resultado:

[ { name: ''pineapple'', id: ''ab982d34c98f'' }, { name: ''carrots'', id: ''6f12e6ba45ec'' } ]

Tal vez no sea la mejor forma de rendimiento, pero es bastante elegante.


Si quieres hacerlo un poco más reutilizable. Tal vez este es un enfoque decente.

function rekey(arr, lookup) { for (var i = 0; i < arr.length; i++) { var obj = arr[i]; for (var fromKey in lookup) { var toKey = lookup[fromKey]; var value = obj[fromKey]; if (value) { obj[toKey] = value; delete obj[fromKey]; } } } return arr; } var arr = [{ apple: ''bar'' }, { apple: ''foo'' }]; var converted = rekey(arr, { apple: ''kung'' }); console.log(converted);


Utilizando ES6:

const renameFieldInArrayOfObjects = (arr, oldField, newField) => { return arr.map(s => { return Object.keys(s).reduce((prev, next) => { if(next === oldField) { prev[newField] = s[next] } else { prev[next] = s[next] } return prev }, {}) }) }

Utilizando ES7:

const renameFieldInArrayOfObjects = (arr, oldField, newField) => { return arr.map(s => { return Object.keys(s).reduce((prev, next) => { return next === oldField ? {...prev, [newField]: s[next]} : {...prev, [next]: s[next]} }, {}) }) }


var jsonObj = [/*sample array in question*/ ]

Basado en los diferentes puntos de referencia que se analizan a continuación, la solución más rápida es nativa para:

var arr = []; for(var i = 0, len = jsonObj .length; i < len; i++) { arr.push( {"name": jsonObj[i].title, "id" : jsonObj[i].uid}); }

Creo que, alternativamente, sin usar marcos, esta será la opción 2:

var arr = [] jsonObj.forEach(function(item) { arr.push({"name": item.title, "id" : item.uid }); });

Siempre hay un debate entre el uso de navite y las funciones no-navite. Si recuerdo correctamente, lodash argumentó que eran más rápidos que el subrayado porque utilizan funciones no nativas para las operaciones clave.

Sin embargo, diferentes navegadores producirán a veces resultados muy diferentes. Siempre busqué el mejor promedio.

Para los puntos de referencia puede echar un vistazo a esto:

http://jsperf.com/lo-dash-v1-1-1-vs-underscore-v1-4-4/8