Hay un inteligente (es decir, optimizado) manera de cambiar el nombre de una clave en un objeto de javascript?

No optimizado forma sería:

o[ new_key ] = o[ old_key ];
delete o[ old_key ];
  • ¿Qué entiende usted por «optimizado»? Creo que no puede ser más escueto que eso; no hay que «cambiar el nombre de» built-en la operación.
  • Que es todo lo que puedes conseguir. Me gustaría preocuparse de otras cosas en mi aplicación. Y por cierto, estás tratando con objetos, no de las matrices. No hay matrices asociativas en JavaScript (en sentido estricto).
  • Optimizado sería ya sea más rápido o más compacto o más legible.
  • Vincent: ¿lento?
  • esta es la más optimizada y la versión básica
  • no muy lento, pero al menos feo, y podría convertirse en un problema una vez que el uso de subprocesos de trabajo.
  • su versión es la más rápida en todos los navegadores modernos, excepto safari, ejemplo de caso de prueba @ jsperf.com/livi-006
  • Estoy muy curioso en cuanto a por qué se quiere hacer esto. Como @Felix ya se dijo, es un objeto de modo que usted no puede realmente cambiar el nombre de las llaves’, porque son propiedades de los objetos. Por lo tanto, si desea cambiar el nombre de las teclas sobre una base regular, tal vez usted debería usar un tipo diferente de estructura de datos? ¿Qué estás usando para?
  • Subprocesos de trabajo en el principio de la transmisión de mensajes (pasar y devolver una cadena JSON); ellos no hacen memoria compartida, si esa es tu preocupación. Si usted está buscando una menos «feo» solución considere la posibilidad de colocar en una función como @hunter sugiere o ampliar el objeto de Matriz mediante la adición de un cambiar el nombre de método del prototipo.
  • Norman, yo uso un servicio web que devuelve JSON con ALL_CAPS claves de objeto. Me gustaría cambiar el nombre de estas claves.
  • Cambiado «matriz» a «objeto» como acertadamente lo sugerido por varios comentaristas.
  • Vicente Ah, ya veo. En ese caso, creo que podría ser mejor (y que, como resulta, más rápido) para crear un nuevo objeto que representa lo que usted desea hacer con los datos después de que se ha recuperado desde el servicio web. Véase también mi respuesta 🙂
  • si usted utiliza node.js usted podría tratar de npmjs.com/package/rename-keys
  • esto se ve muy bien, pero parece que recorre, y hace los cambios, todas las claves? Para abordar una clave específica, supongo que se podría hacer: if (key === "_x") { return "x"; } else { return key; }

InformationsquelleAutor Jean Vincent | 2011-01-10

17 Comentarios

  1. 160

    La más completa (y correcta) manera de hacer esto sería, creo yo:

    if (old_key !== new_key) {
        Object.defineProperty(o, new_key,
            Object.getOwnPropertyDescriptor(o, old_key));
        delete o[old_key];
    }

    Este método garantiza que el hotel renombrado se comporta de forma idéntica a la original.

    También, a mí me parece que la posibilidad de terminar en una función/método y ponerlo en Object.prototype es irrelevante en cuanto a tu pregunta.

    • Este es un buen ES5-la única solución con la real, además de conservar todas las propiedades. Así que esto no es «optimizado», pero definitivamente más precisa en ES5.
    • upvoted con cierto escepticismo hacia writing_things_with_underscores, pero por supuesto que era debido a la persona que hace la pregunta. esta es la respuesta correcta, en mi opinión.
    • En caso de que importa, creo que este uso particular de ES5 es una IE9-y-más reciente de la solución.
    • más lento
    • Te sugiero agregar una validación de que o’.old_key existe. Cambio: if (old_key !== new_key) a: if (old_key !== new_key && o[old_key])
  2. 89

    Usted podría ajustar el trabajo en una función y asignar a la Object prototipo. Tal vez de usar la interfaz fluida estilo de hacer varios cambia el nombre de flujo.

    Object.prototype.renameProperty = function (oldName, newName) {
         //Do nothing if the names are the same
         if (oldName == newName) {
             return this;
         }
        //Check for the old property name to avoid a ReferenceError in strict mode.
        if (this.hasOwnProperty(oldName)) {
            this[newName] = this[oldName];
            delete this[oldName];
        }
        return this;
    };

    ECMAScript 5 Específicos

    Me gustaría que la sintaxis no era de este complejo pero definitivamente es agradable tener más control.

    Object.defineProperty(
        Object.prototype, 
        'renameProperty',
        {
            writable : false, //Cannot alter this property
            enumerable : false, //Will not show up in a for-in loop.
            configurable : false, //Cannot be deleted via the delete operator
            value : function (oldName, newName) {
                //Do nothing if the names are the same
                if (oldName == newName) {
                    return this;
                }
                //Check for the old property name to 
                //avoid a ReferenceError in strict mode.
                if (this.hasOwnProperty(oldName)) {
                    this[newName] = this[oldName];
                    delete this[oldName];
                }
                return this;
            }
        }
    );
    • lo siento, pero estoy muy cansado de error montado el código JS, actualmente estoy escribiendo una Guía (github.com/BonsaiDen/JavaScript-Garden) acerca de todas las peculiaridades (incluyendo el que ahora tienes fijo), esto podría me han puesto en una especie de diatriba modo 😉 (se elimina el -1 ahora)
    • Podría usted explicar por qué se siente ampliar el prototipo es malo? Los prototipos fueron hechas para la ampliación de bebé!
    • No la indígenas uno, porque introducen todo el lío con in etc. Prototype.js es un gran ejemplo porque es malo, incluso sus desarrolladores han admitido que se trataba de un mal uso de la biblioteca.
    • Estoy de acuerdo en que es arriesgado, pero no hay nada que me hará dejar de extender el prototipo si sentí que conducen a la más expresiva de código. Aunque vengo de un ECMAScript 5 mentalidad que puede marcar una propiedad como no enumerable a través de Object.defineProperty.
    • Si es adecuada la práctica de utilizar siempre hasOwnProperty para comprobar las propiedades y dentro de for ... in bucles, entonces ¿por qué importa si ampliamos el Objeto?
    • debe ser una práctica estándar, pero no lo es, especialmente entre los «estándar» de los desarrolladores.
    • Este código funciona, pero la advertencia es que si el nuevo nombre de la clave ya existe, su valor va a bajar pisado: jsfiddle.net/ryurage/B7x8x
    • Me encontré con este también. He añadido una solución simple, con la legibilidad en mente.

  3. 44

    Si usted está mutando su objeto de origen, ES6 puede hacer en una sola línea.

    delete Object.assign(o, {[newKey]: o[oldKey] })[oldKey];

    O dos líneas si desea crear un nuevo objeto.

    const newObject = {};
    delete Object.assign(newObject, o, {[newKey]: o[oldKey] })[oldKey];
    • Trate de: eliminar el Objeto.asignar(o, {newKey: o.oldKey }).oldKey; Funcionado bien para mí
    • Forma inteligente de resolver el problema!
    • ¿Por qué existe la plaza de la llave de [] alrededor de newKey? La solución funciona sin que en realidad.
    • Ok – tengo mi respuesta. Es la ES6 característica. Para nadie encontré en este como yo, aquí es una buena respuesta.
    • Esta respuesta sería más fuerte si tu los nombres de las variables fueron más detallado.
  4. 30

    En caso de que alguien necesita para cambiar el nombre de una lista de propiedades:

    function renameKeys(obj, newKeys) {
      const keyValues = Object.keys(obj).map(key => {
        const newKey = newKeys[key] || key;
        return { [newKey]: obj[key] };
      });
      return Object.assign({}, ...keyValues);
    }

    Uso:

    const obj = { a: "1", b: "2" };
    const newKeys = { a: "A", c: "C" };
    const renamedObj = renameKeys(obj, newKeys);
    console.log(renamedObj);
    //{A:"1", b:"2"}
    • esto debe ser aceptado respuesta, trabajó mucho para mi caso de uso. He tenido que convertir una API de respuesta que fue el prefijo de País de Nombres con la innecesaria de la cadena. Se volvió Objeto en una matriz de teclas y se asignan a través de cada tecla con el método substring y devuelve un nuevo objeto con la nueva clave y valor indexado por la llave de la original
  5. 17

    Me gustaría simplemente utilizando el ES6(ES2015) manera!

    necesitamos mantener el ritmo con los tiempos!

    JS:

    const old_obj = {
        k1: `111`,
        k2: `222`,
        k3: `333`
    };
    console.log(`old_obj =\n`, old_obj);
    //{k1: "111", k2: "222", k3: "333"}
    
    
    /**
     * @author xgqfrms
     * @description ES6 ...spread & Destructuring Assignment
     */
    
    const {
        k1: kA, 
        k2: kB, 
        k3: kC,
    } = {...old_obj}
    
    console.log(`kA = ${kA},`, `kB = ${kB},`, `kC = ${kC}\n`);
    //kA = 111, kB = 222, kC = 333
    
    const new_obj = Object.assign(
        {},
        {
            kA,
            kB,
            kC
        }
    );
    
    console.log(`new_obj =\n`, new_obj);
    //{kA: "111", kB: "222", kC: "333"}

    JavaScript: Objeto De Cambiar El Nombre De La Clave

    • Este es uno como limpiador de solución cuando se quiere transformar un objeto con formato incorrecto para un nuevo reestructurado uno.
    • Bueno, pero creo que const {k1: kA, k2: kB, k3: kC,} = old_obj es suficiente? no hay necesidad de la expansión de (a menos que desee una copia de old_obj).
    • sí, estás en lo correcto. Pero en esta situación, quiero cambiar el nombre de algunas de las claves, así que debo a su difusión.
    • Esto requiere de mucho más código, será menos eficiente, y crea un nuevo objeto. Cambio de nombre de una propiedad implica la mutación del objeto. Más reciente, no siempre es mejor.
  6. 5

    Una variación utilizando el objeto de desestructuración y la propagación del operador:

        const old_obj = {
            k1: `111`,
            k2: `222`,
            k3: `333`
        };
    
    
    //destructuring, with renaming. The variable rest will hold those values not assigned to kA, kB, or kC.
        const {
            k1: kA, 
            k2: kB, 
            k3: kC,
            ...rest
        } = old_obj;
    
    
    //now create a new object, with shorthand properties **kA, kB, kC**; 
    //spread the remaining properties in the **rest** variable
    const newObj = {kA, kB, kC, ...rest};
    • Tal vez usted podría explicar lo que esto está haciendo y cómo funciona?
    • hecho.
  7. 4

    Me gustaría hacer algo como esto:

    function renameKeys(dict, keyMap) {
      return _.reduce(dict, function(newDict, val, oldKey) {
        var newKey = keyMap[oldKey] || oldKey
        newDict[newKey] = val 
        return newDict
      }, {})
    }
    • Hizo una versión actualizada de su solución, que no transforma claves estáticas a ‘undefined’ aquí: gist.github.com/diasdavid/f8997fb0bdf4dc1c3543 sin Embargo, aún no tiene el problema de querer volver a asignar teclas a varios niveles del objeto JSON (remaping anidada teclas), ideas?
  8. 4

    Puede intentar lodash _.mapKeys.

    JS:

    var user = {
      name: "Andrew",
      id: 25,
      reported: false
    };
    
    var renamed = _.mapKeys(user, function(value, key) {
      return key + "_" + user.id;
    });
    
    console.log(renamed);

    HTML:

    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>

  9. 3

    Yo diría que sería mejor desde un punto de vista conceptual dejar el objeto viejo (el de la web del servicio) como es, y poner los valores que usted necesita en un nuevo objeto. Estoy asumiendo que usted está extracción de campos específicos en un momento u otro de todos modos, si no en el cliente, al menos en el servidor. El hecho de que usted eligió para el uso de los nombres de campo que son las mismas que las de la web del servicio, sólo minúsculas, no cambia esto. Así que, te aconsejo de hacer algo como esto:

    var myObj = {
        field1: theirObj.FIELD1, 
        field2: theirObj.FIELD2,
        (etc)
    }

    Por supuesto, estoy haciendo todo tipo de suposiciones aquí, que no puede ser cierto. Si esto no se aplica a usted, o si es demasiado lenta (es? Yo no lo he probado, pero me imagino que la diferencia se hace menor a medida que el número de campos de aumentos), por favor ignorar todo esto 🙂

    Si usted no quiere hacer esto, y usted sólo tiene, para el apoyo de los navegadores, también se pueden usar los nuevos captadores para volver «en mayúsculas(campo)»: ver http://robertnyman.com/2009/05/28/getters-and-setters-with-javascript-code-samples-and-demos/ y los enlaces en esta página para obtener más información.

    EDICIÓN:

    Increíblemente, este es también casi el doble de rápido, al menos en mi FF3.5 en el trabajo. Ver: http://jsperf.com/spiny001

    • Muchas gracias por sus esfuerzos, pero el caso de uso no manipular objetos estáticos como su estructura y la profundidad es desconocido. Así que si es posible me gustaría palo para el alcance original de la pregunta.
  10. 2

    Algunas de las soluciones que aparecen en esta página tienen algunos efectos secundarios:

    1. afectar a la posición de la llave en el objeto, añadiendo a la parte inferior (si te interesa)
    2. no funciona en IE9+ (de nuevo, si esto es importante para usted)

    Aquí es una solución que mantiene la posición de la llave en el mismo lugar y es compatible en IE9+, pero tiene que crear un nuevo objeto y puede no ser la solución más rápida:

    function renameObjectKey(oldObj, oldName, newName) {
        const newObj = {};
    
        Object.keys(oldObj).forEach(key => {
            const value = oldObj[key];
    
            if (key === oldName) {
                newObj[newName] = value;
            } else {
                newObj[key] = value;
            }
        });
    
        return newObj;
    }

    Por favor nota: IE9 no puede apoyar forEach en modo estricto

  11. 2

    La mayoría de las respuestas aquí no mantener JS Objeto de pares clave-valor de la orden. Si usted tiene un tipo de objeto de pares clave-valor en la pantalla que desea modificar, por ejemplo, es importante para preservar el orden de los objetos de entradas.

    La ES6 forma de bucle a través de la JS objeto y la sustitución de par clave-valor con la nueva pareja con una modificación de clave de nombre sería algo como:

    let newWordsObject = {};
    
    Object.keys(oldObject).forEach(key => {
      if (key === oldKey) {
        let newPair = { [newKey]: oldObject[oldKey] };
        newWordsObject = { ...newWordsObject, ...newPair }
      } else {
        newWordsObject = { ...newWordsObject, [key]: oldObject[key] }
      }
    });

    La solución se conserva el orden de las entradas mediante la adición de la nueva entrada en el lugar de la antigua.

  12. 1

    Personalmente, la forma más efectiva para cambiar el nombre de las teclas en el objeto sin la aplicación de extra pesado plugins y ruedas:

    var str = JSON.stringify(object);
    str = str.replace(/oldKey/g, 'newKey');
    str = str.replace(/oldKey2/g, 'newKey2');
    
    object = JSON.parse(str);

    También puedes envolverlo en try-catch si el objeto tiene estructura no válido. Funciona perfectamente 🙂

    • ooops! var objeto = {b : ‘123’, ‘c’ : ‘bbb’}; var str = JSON.stringify(objeto); str = str.replace(/b/g, ‘newKey’); str = str.replace(/c/g, ‘newKey2’); objeto = JSON.parse(str);
    • ¿Cómo se compara la velocidad?
    • También se ejecuta en un potencial problema de algún lugar en el datavalues es la misma cadena que el antiguo nombre de la clave.
    • «Funciona perfectamente» para algunas de las definiciones de «perfección». Intente cambiar el nombre de 'a' en { a: 1, aa: 2, aaa: 3} o intentar cambiar el nombre de un objeto con los valores que son nada más que cadenas de caracteres o números o valores booleanos, o probar con referencias circulares.
    • si el objeto contiene la función o la fecha de objetos, esto no va a funcionar
    • Esto realmente es un horrendo solución

  13. 1

    Mientras esto no exactamente a dar una mejor solución para cambiar el nombre de una clave, proporciona una manera rápida y fácil ES6 manera de cambiar el nombre de todas las claves de un objeto mientras no la mutación de los datos que contienen.

    let b = {a: ["1"], b:["2"]};
    Object.keys(b).map(id => {
      b[`root_${id}`] = [...b[id]];
      delete b[id];
    });
    console.log(b);
    • Atención a los detalles sobre lo que han hecho y por qué?
    • Por favor, utilice el editar enlace para explicar cómo este código funciona y no acaba de dar el código, como una explicación es la más probable para ayudar a los futuros lectores. Véase también Cómo Responder. fuente
    • Estoy de acuerdo. No responde a la pregunta en concreto, pero me ayudó en la realización del trabajo como una solución para cambiar el nombre de todas las claves en el objeto. Tal vez se me perdió el tema..
  14. 1

    Aquí hay un ejemplo para crear un nuevo objeto cambiado el nombre de las teclas.

    let x = { id: "checkout", name: "git checkout", description: "checkout repository" };
    
    let renamed = Object.entries(x).reduce((u, [n, v]) => {
      u[`__${n}`] = v;
      return u;
    }, {});
  15. 0

    Esta es una pequeña modificación que le hice a la función de pomber;
    Para ser capaz de tomar un Array de Objetos en lugar de un objeto solo y también se puede activar índice. también las «Claves» que puede ser asignado por una matriz

    function renameKeys(arrayObject, newKeys, index = false) {
        let newArray = [];
        arrayObject.forEach((obj,item)=>{
            const keyValues = Object.keys(obj).map((key,i) => {
                return {[newKeys[i] || key]:obj[key]}
            });
            let id = (index) ? {'ID':item} : {}; 
            newArray.push(Object.assign(id, ...keyValues));
        });
        return newArray;
    }

    prueba

    const obj = [{ a: "1", b: "2" }, { a: "5", b: "4" } ,{ a: "3", b: "0" }];
    const newKeys = ["A","C"];
    const renamedObj = renameKeys(obj, newKeys);
    console.log(renamedObj);
  16. 0

    Su camino está optimizado, en mi opinión. Pero usted va a terminar con reordenar las teclas. La clave recién creada se añade al final. Sé que no debería confiar en orden de clave, pero si usted necesita para preservarlo, usted tendrá que ir a través de todas las claves de la construcción de nuevos objetos, uno por uno, en sustitución de la clave en cuestión durante ese proceso.

    Como este:

    var new_o={};
    for (var i in o)
    {
       if (i==old_key) new_o[new_key]=o[old_key];
       else new_o[i]=o[i];
    }
    o=new_o;
    • Esto no funciona para mí.

Dejar respuesta

Please enter your comment!
Please enter your name here