Existe-t-il un moyen intelligent (c'est-à-dire optimisé) de renommer une clé dans un objet javascript?
Une manière non optimisée serait:
o[ new_key ] = o[ old_key ];
delete o[ old_key ];
Existe-t-il un moyen intelligent (c'est-à-dire optimisé) de renommer une clé dans un objet javascript?
Une manière non optimisée serait:
o[ new_key ] = o[ old_key ];
delete o[ old_key ];
Réponses:
La façon la plus complète (et correcte) de procéder serait, je crois:
if (old_key !== new_key) {
Object.defineProperty(o, new_key,
Object.getOwnPropertyDescriptor(o, old_key));
delete o[old_key];
}
Cette méthode garantit que la propriété renommée se comporte de manière identique à la propriété d'origine.
De plus, il me semble que la possibilité d'envelopper cela dans une fonction / méthode et de l'intégrer Object.prototype
n'est pas pertinente en ce qui concerne votre question.
if (old_key !== new_key)
vers: if (old_key !== new_key && o[old_key])
Vous pouvez envelopper le travail dans une fonction et l'affecter au Object
prototype. Peut-être utiliser le style d'interface fluide pour faire couler plusieurs renommages.
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;
};
Spécifique à ECMAScript 5
Je souhaite que la syntaxe ne soit pas aussi complexe mais c'est vraiment bien d'avoir plus de contrôle.
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;
}
}
);
Object.defineProperty
.
hasOwnProperty
pour vérifier les propriétés et les for ... in
boucles, alors pourquoi est-ce important si nous étendons Object?
Si vous mutez votre objet source, ES6 peut le faire sur une seule ligne.
delete Object.assign(o, {[newKey]: o[oldKey] })[oldKey];
Ou deux lignes si vous souhaitez créer un nouvel objet.
const newObject = {};
delete Object.assign(newObject, o, {[newKey]: o[oldKey] })[oldKey];
[]
autour newKey
? La solution fonctionne sans cela en fait.
Si quelqu'un doit renommer une liste de propriétés:
function renameKeys(obj, newKeys) {
const keyValues = Object.keys(obj).map(key => {
const newKey = newKeys[key] || key;
return { [newKey]: obj[key] };
});
return Object.assign({}, ...keyValues);
}
Usage:
const obj = { a: "1", b: "2" };
const newKeys = { a: "A", c: "C" };
const renamedObj = renameKeys(obj, newKeys);
console.log(renamedObj);
// {A:"1", b:"2"}
my_object_property
en myObjectProperty
, cependant, si ma propriété était composée d'un seul mot, la clé a été supprimée. +1
ES6(ES2015)
chemin!nous devons suivre le temps!
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"}
Si vous ne voulez pas muter vos données, pensez à cette fonction ...
renameProp = (oldProp, newProp, {[oldProp]:old, ...others}) => ({
[newProp]: old,
...others
})
Une explication approfondie par Yazeed Bzadough https://medium.com/front-end-hacking/immutably-rename-object-keys-in-javascript-5f6353c7b6dd
La plupart des réponses ici ne parviennent pas à maintenir l'ordre des paires clé-valeur de l'objet JS. Si vous avez une forme de paires clé-valeur d'objet à l'écran que vous souhaitez modifier, par exemple, il est important de conserver l'ordre des entrées d'objet.
La façon ES6 de parcourir l'objet JS et de remplacer la paire clé-valeur par la nouvelle paire avec un nom de clé modifié serait quelque chose comme:
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 solution préserve l'ordre des entrées en ajoutant la nouvelle entrée à la place de l'ancienne.
Vous pouvez essayer le lodash _.mapKeys
.
var user = {
name: "Andrew",
id: 25,
reported: false
};
var renamed = _.mapKeys(user, function(value, key) {
return key + "_" + user.id;
});
console.log(renamed);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
Une variation utilisant l'opérateur de déstructuration et de propagation d'objets:
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 the renamed properties kA, kB, kC;
// spread the remaining original properties in the 'rest' variable
const newObj = {kA, kB, kC, ...rest};
Personnellement, le moyen le plus efficace pour renommer des clés dans un objet sans implémenter des plugins et des roues très lourds:
var str = JSON.stringify(object);
str = str.replace(/oldKey/g, 'newKey');
str = str.replace(/oldKey2/g, 'newKey2');
object = JSON.parse(str);
Vous pouvez également l'envelopper try-catch
si votre objet a une structure non valide. Fonctionne parfaitement :)
'a'
dans { a: 1, aa: 2, aaa: 3}
ou essayer de renommer un objet avec des valeurs qui ne sont rien de plus que des chaînes ou des nombres ou des booléens, ou essayez avec des références circulaires.
Je ferais quelque chose comme ça:
function renameKeys(dict, keyMap) {
return _.reduce(dict, function(newDict, val, oldKey) {
var newKey = keyMap[oldKey] || oldKey
newDict[newKey] = val
return newDict
}, {})
}
Je dirais qu'il serait préférable d'un point de vue conceptuel de laisser simplement l'ancien objet (celui du service Web) tel quel et de mettre les valeurs dont vous avez besoin dans un nouvel objet. Je suppose que vous extrayez des champs spécifiques à un moment ou à un autre de toute façon, sinon sur le client, du moins sur le serveur. Le fait que vous ayez choisi d'utiliser des noms de champs identiques à ceux du service Web, uniquement en minuscules, ne change rien à cela. Donc, je vous conseille de faire quelque chose comme ça:
var myObj = {
field1: theirObj.FIELD1,
field2: theirObj.FIELD2,
(etc)
}
Bien sûr, je fais toutes sortes d'hypothèses ici, ce qui n'est peut-être pas vrai. Si cela ne s'applique pas à vous, ou si c'est trop lent (est-ce? Je n'ai pas testé, mais j'imagine que la différence diminue avec l'augmentation du nombre de champs), veuillez ignorer tout cela :)
Si vous ne voulez pas le faire, et que vous ne devez prendre en charge que des navigateurs spécifiques, vous pouvez également utiliser les nouveaux getters pour renvoyer également "majuscule (champ)": voir http://robertnyman.com/2009/05/28 / getters-and-setters-with-javascript-code-samples-and-demos / et les liens sur cette page pour plus d'informations.
ÉDITER:
Incroyablement, c'est aussi presque deux fois plus rapide, au moins sur mon FF3.5 au travail. Voir: http://jsperf.com/spiny001
Bien que cela ne donne pas exactement une meilleure solution pour renommer une clé, il fournit un moyen ES6 rapide et facile de renommer toutes les clés d'un objet sans muter les données qu'elles contiennent.
let b = {a: ["1"], b:["2"]};
Object.keys(b).map(id => {
b[`root_${id}`] = [...b[id]];
delete b[id];
});
console.log(b);
Certaines des solutions répertoriées sur cette page ont des effets secondaires:
Voici une solution qui conserve la position de la clé au même endroit et est compatible dans IE9 +, mais doit créer un nouvel objet et peut ne pas être la solution la plus rapide:
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;
}
Remarque: IE9 peut ne pas prendre en charge forEach en mode strict
Encore une autre façon avec la méthode REDUCE la plus puissante .
data = {key1: "value1", key2: "value2", key3: "value3"};
keyMap = {key1: "firstkey", key2: "secondkey", key3: "thirdkey"};
mappedData = Object.keys(keyMap).reduce((obj,k) => Object.assign(obj, { [keyMap[k]]: data[k] }),{});
console.log(mappedData);
Ceci est une petite modification que j'ai apportée à la fonction de bombardier; Pour pouvoir prendre un tableau d'objets au lieu d'un objet seul et vous pouvez également activer l'index. les "clés" peuvent également être attribuées par un tableau
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;
}
tester
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);
Votre chemin est optimisé, à mon avis. Mais vous vous retrouverez avec des clés réorganisées. La clé nouvellement créée sera ajoutée à la fin. Je sais que vous ne devriez jamais vous fier à l'ordre des clés, mais si vous devez le conserver, vous devrez parcourir toutes les clés et construire un nouvel objet un par un, en remplaçant la clé en question pendant ce processus.
Comme ça:
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;
npm i paix
import { paix } from 'paix';
const source_object = { FirstName: "Jhon", LastName: "Doe", Ignored: true };
const replacement = { FirstName: 'first_name', LastName: 'last_name' };
const modified_object = paix(source_object, replacement);
console.log(modified_object);
// { Ignored: true, first_name: 'Jhon', last_name: 'Doe' };