对象重命名键

是否有一个聪明的(即优化)方法重命名一个关键在javascript对象?

一种非优化的方式是:

o[ new_key ] = o[ old_key ];
delete o[ old_key ];
549118 次浏览

你可以将工作包装在一个函数中,并将其分配给Object原型。也许可以使用流畅的界面样式使多个重命名流动。

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 Specific

我希望语法不是这么复杂,但它肯定是很好的有更多的控制。

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;
}
}
);

我想说,从概念的角度来看,保持旧对象(来自web服务的对象)原样,并将所需的值放在新对象中会更好。我假设您在某个地方提取特定的字段,如果不是在客户机上,那么至少是在服务器上。事实上,您选择使用与web服务相同的字段名,只是小写,这并没有真正改变这一点。所以,我建议你这样做:

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

当然,我在这里做了各种各样的假设,这可能是不正确的。如果这对你不适用,或者它太慢了(是吗?我还没有测试过,但我想随着字段数量的增加,差异会越来越小),请忽略所有这些:)

如果你不想这样做,并且你只需要支持特定的浏览器,你也可以使用新的getter来返回“大写(字段)”。:更多信息请参见http://robertnyman.com/2009/05/28/getters-and-setters-with-javascript-code-samples-and-demos/和该页面的链接。

编辑:

令人难以置信的是,这也几乎是两倍的速度,至少在我的FF3.5工作。看:http://jsperf.com/spiny001

我认为最完整(和正确)的方法是:

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

此方法确保重命名的属性行为完全相同为原始属性。

此外,在我看来,将其包装成函数/方法并将其放入Object.prototype的可能性与您的问题无关。

我会这样做:

function renameKeys(dict, keyMap) {
return _.reduce(dict, function(newDict, val, oldKey) {
var newKey = keyMap[oldKey] || oldKey
newDict[newKey] = val
return newDict
}, {})
}

就我个人而言,重命名对象中的键而不实现额外的沉重插件和轮子的最有效的方法:

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


object = JSON.parse(str);

如果对象的结构无效,也可以将其包装在try-catch中。工作完美无缺:)

虽然这并不是一个更好的重命名键的解决方案,但它提供了一种快速简单的ES6方法来重命名对象中的所有键,同时不改变它们所包含的数据。

let b = {a: ["1"], b:["2"]};
Object.keys(b).map(id => {
b[`root_${id}`] = [...b[id]];
delete b[id];
});
console.log(b);

如果有人需要重命名属性列表:

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

用法:

const obj = { a: "1", b: "2" };
const newKeys = { a: "A", c: "C" };
const renamedObj = renameKeys(obj, newKeys);
console.log(renamedObj);
// {A:"1", b:"2"}

我想只使用ES6(ES2015)的方式!

我们需要跟上时代!

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"}

demo屏幕快捷方式

本页列出的一些解决方案有一些副作用:

  1. 影响键在对象中的位置,将其添加到底部(如果这对你来说很重要)
  2. 不能在IE9+中工作(如果这对你来说很重要的话)

下面是一个解决方案,它保持键的位置在相同的地方,并在IE9+兼容,但必须创建一个新的对象,可能不是最快的解决方案:

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;
}

请注意:IE9在严格模式下可能不支持forEach

如果你不想改变你的数据,考虑这个函数…

renameProp = (oldProp, newProp, { [oldProp]: old, ...others }) => ({
[newProp]: old,
...others
})
Yazeed Bzadough的详细解释 https://medium.com/front-end-hacking/immutably-rename-object-keys-in-javascript-5f6353c7b6dd < / p >

下面是一个typescript友好的版本:

// These generics are inferred, do not pass them in.
export const renameKey = <
OldKey extends keyof T,
NewKey extends string,
T extends Record<string, unknown>
>(
oldKey: OldKey,
newKey: NewKey extends keyof T ? never : NewKey,
userObject: T
): Record<NewKey, T[OldKey]> & Omit<T, OldKey> => {
const { [oldKey]: value, ...common } = userObject


return {
...common,
...({ [newKey]: value } as Record<NewKey, T[OldKey]>)
}
}

它将防止您破坏现有的键或将其重命名为相同的东西

如果你要改变源对象,ES6可以在一行中完成。

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

如果你想创建一个新对象,可以用两行。

const newObject = {};
delete Object.assign(newObject, o, {[newKey]: o[oldKey] })[oldKey];
这是我对pomber函数做的一个小修改; 为了能够获取一个对象数组而不是单独的对象,你也可以激活索引。此外,“键”也可以由数组

分配
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;
}

测验

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);

下面是创建具有重命名键的新对象的示例。

let x = { id: "checkout", name: "git checkout", description: "checkout repository" };


let renamed = Object.entries(x).reduce((u, [n, v]) => {
u[`__${n}`] = v;
return u;
}, {});

你可以试试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>

使用对象解构和展开运算符的变体:

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};

对于一个键,这可以很简单:

const { k1: kA, ...rest } = old_obj;
const new_obj = { kA, ...rest }

你也可能喜欢更“传统”的风格:

const { k1, ...rest } = old_obj
const new_obj = { kA: k1, ...rest}

在我看来,你的方法是最优化的。但你最终会得到重新排序的密钥。新创建的密钥将附加在末尾。我知道你不应该依赖键的顺序,但如果你需要保存它,你将需要遍历所有键并一个接一个地构造新对象,在这个过程中替换有问题的键。

是这样的:

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;

这里的大多数答案都无法维持JS对象键值对的顺序。例如,如果您在屏幕上有一种希望修改的对象键-值对形式,那么保持对象条目的顺序就很重要。

ES6循环JS对象并将键值对替换为具有修改过的键名的新键值对的方法如下:

let newWordsObject = {};


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

该解决方案通过在旧条目的位置上添加新条目来保留条目的顺序。

为每个键添加前缀:

const obj = {foo: 'bar'}


const altObj = Object.fromEntries(
Object.entries(obj).map(([key, value]) =>
// Modify key here
[`x-${key}`, value]
)
)


// altObj = {'x-foo': 'bar'}
  • 您可以使用实用程序来处理这个问题。
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' };


还有一种最强大的减少方法。

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);
// { "firstkey": "value1", "secondkey": "value2", "thirdkey": "value3"}

在你最喜欢的编辑器中试试吧

const obj = {1: 'a', 2: 'b', 3: 'c'}


const OLD_KEY = 1
const NEW_KEY = 10


const { [OLD_KEY]: replaceByKey, ...rest } = obj
const new_obj = {
...rest,
[NEW_KEY]: replaceByKey
}

尝试使用lodash transform。

var _ = require('lodash');


obj = {
"name": "abc",
"add": "xyz"
};


var newObject = _.transform(obj, function(result, val, key) {


if (key === "add") {
result["address"] = val
} else {
result[key] = val
}
});
console.log(obj);
console.log(newObject);
const data = res
const lista = []
let newElement: any


if (data && data.length > 0) {


data.forEach(element => {
newElement = element


Object.entries(newElement).map(([key, value]) =>
Object.assign(newElement, {
[key.toLowerCase()]: value
}, delete newElement[key], delete newElement['_id'])
)
lista.push(newElement)
})
}
return lista
const clone = (obj) => Object.assign({}, obj);


const renameKey = (object, key, newKey) => {


const clonedObj = clone(object);
  

const targetKey = clonedObj[key];
  

  

  

delete clonedObj[key];
  

clonedObj[newKey] = targetKey;
  

return clonedObj;
};


let contact = {radiant: 11, dire: 22};










contact = renameKey(contact, 'radiant', 'aplha');


contact = renameKey(contact, 'dire', 'omega');






console.log(contact); // { aplha: 11, omega: 22 };

重命名键,但避免改变原始对象参数

oldJson=[{firstName:'s1',lastName:'v1'},
{firstName:'s2',lastName:'v2'},
{firstName:'s3',lastName:'v3'}]


newJson = oldJson.map(rec => {
return {
'Last Name': rec.lastName,
'First Name': rec.firstName,
}
})
output: [{Last Name:"v1",First Name:"s1"},
{Last Name:"v2",First Name:"s2"},
{Last Name:"v3",First Name:"s3"}]

最好有一个新的数组

简单地这么做会有什么问题吗?

someObject = {...someObject, [newKey]: someObject.oldKey}
delete someObject.oldKey

如果愿意,可以将其包装在函数中:

const renameObjectKey = (object, oldKey, newKey) => {
// if keys are the same, do nothing
if (oldKey === newKey) return;
// if old key doesn't exist, do nothing (alternatively, throw an error)
if (!object.oldKey) return;
// if new key already exists on object, do nothing (again - alternatively, throw an error)
if (object.newKey !== undefined) return;


object = { ...object, [newKey]: object[oldKey] };
delete object[oldKey];


return { ...object };
};

// in use
let myObject = {
keyOne: 'abc',
keyTwo: 123
};


// avoids mutating original
let renamed = renameObjectKey(myObject, 'keyTwo', 'renamedKey');


console.log(myObject, renamed);
// myObject
/* {
"keyOne": "abc",
"keyTwo": 123,
} */


// renamed
/* {
"keyOne": "abc",
"renamedKey": 123,
} */

如果你想保留迭代顺序(插入的顺序),这里有一个建议:

const renameObjectKey = (object, oldName, newName) => {


const updatedObject = {}


for(let key in object) {
if (key === oldName) {
newObject[newName] = object[key]
} else {
newObject[key] = object[key]
}
}


object = updatedObject
}

我的方法,调整不错的@Mulhoon打字稿,用于更改多个键:

const renameKeys = <
TOldKey extends keyof T,
TNewkey extends string,
T extends Record<string, unknown>
>(
keys:  {[ key: string]: TNewkey extends TOldKey ? never : TNewkey },
obj: T
) => Object
.keys(obj)
.reduce((acc, key) => ({
...acc,
...{ [keys[key] || key]: obj[key] }
}), {});


renameKeys({id: 'value', name: 'label'}, {id: 'toto_id', name: 'toto', age: 35});

重命名对象键的另一种方法:

让我们考虑这个对象:

let obj = {"name": "John", "id": 1, "last_name": "Doe"}

让我们重命名name key为first_name:

let { name: first_name, ...rest } = obj;
obj = { first_name, ...rest }

现在对象是:

{"first_name": "John", "id": 1, "last_name": "Doe"}

我想这么做

const originalObj = {
a: 1,
b: 2,
c: 3, // need replace this 'c' key into 'd'
};


const { c, ...rest } = originalObj;


const newObj = { ...rest, d: c };


console.log({ originalObj, newObj });

如果你想保持对象的相同顺序

changeObjectKeyName(objectToChange, oldKeyName: string, newKeyName: string){
const otherKeys = cloneDeep(objectToChange);
delete otherKeys[oldKeyName];


const changedKey = objectToChange[oldKeyName];
return  {...{[newKeyName] : changedKey} , ...otherKeys};


}

使用方法:

changeObjectKeyName ( {'a' : 1}, 'a', 'A');

在寻找了很多答案后,这是我最好的解决方案:

const renameKey = (oldKey, newKey) => {
_.reduce(obj, (newObj, value, key) => {
newObj[oldKey === key ? newKey : key] = value
return newObj
}, {})
}
它没有替换原来的键,而是构造了一个新对象,很明显。 问题中的方法有效,但会改变对象的顺序,因为它在最后一个对象上添加了新的键-值
function iterate(instance) {
for (let child of instance.tree_down) iterate(child);


instance.children = instance.tree_down;
delete instance.tree_down;
}


iterate(link_hierarchy);


console.log(link_hierarchy);

如果有人需要重命名object的键:


const renameKeyObject = (obj, oldKey, newKey) => {
if (oldKey === newKey) return obj;
Object.keys(obj).forEach((key) => {
if (key === oldKey) {
obj[newKey] = obj[key];
delete obj[key];
} else if (obj[key] !== null && typeof obj[key] === "object") {
obj[key] = renameKeyObject(obj[key], oldKey, newKey);
}
});
return obj;
};