JavaScript:对象重命名键

484

有没有一种聪明(即优化)的方式来重命名JavaScript对象中的键?

非优化的方法如下:

o[ new_key ] = o[ old_key ];
delete o[ old_key ];

21
“optimized”是什么意思?我认为这已经非常简洁了,没有内置的“重命名”操作。 - Pointy
12
这就是你能得到的全部。我会担心我的申请中的其他事情。另外,你正在处理对象而不是数组。在JavaScript中(严格意义上),没有关联数组。 - Felix Kling
5
@Jean Vincent: 它速度真的很慢吗? - Felix Kling
12
这是最优化和基础版。 - Livingston Samuel
6
除Safari以外,你的版本在所有现代浏览器中都是最快的。样例测试案例请访问 http://jsperf.com/livi-006。 - Livingston Samuel
显示剩余12条评论
36个回答

14

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

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"}]
最好使用新的数组。

很好,这完美地适合我的使用情况。 - Raqha

12

个人认为,在不使用额外的重型插件和工具的情况下,重新命名对象中的键最有效的方法是:

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

object = JSON.parse(str);

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


15
哎呀! 变量object的值为{b : '123', 'c' : 'bbb'}; 将该对象转换成字符串并赋值给变量str; 用新键值"newKey"替换掉原来键名为"b"的属性名; 用新键值"newKey2"替换掉原来键名为"c"的属性名; 将修改后的字符串重新解析为对象并赋值给变量object。 - BlondinkaBrain
5
这个与速度相比如何? - mix3d
20
可能会遇到一个潜在问题,即数据值中的某个地方与旧键名相同的字符串。 - mix3d
6
对于“完美地工作”,这取决于“完美”的定义。尝试重新命名{ a: 1, aa: 2, aaa: 3 }中的'a',或者尝试重命名具有非字符串、数字或布尔值的值的对象,或者尝试处理循环引用。 - rsp
1
如果对象包含函数或日期对象,则此方法将无法正常工作。 - ikhsan
显示剩余2条评论

11

使用最强大的REDUCE方法的另一种方式。

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


如何在TypeScript中使用它? - Paul Grei

7
我会这样做:

我会这样做:

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

3
我已经更新了你的解决方案,它不会将静态密钥转换为“undefined”,链接在这里:https://gist.github.com/diasdavid/f8997fb0bdf4dc1c3543然而,它仍然没有解决在 JSON 对象的多个级别上想要重新映射键的问题(重新映射嵌套键),有什么想法吗? - David Dias

7

在您最喜欢的编辑器中尝试一下 <3

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
}

1
我似乎无法理解这部分代码: const { [OLD_KEY]: replaceByKey, ...rest } = obj - desh
1
阅读有关对象解构的内容。在这里 - Krishna

6

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

让我们考虑这个对象:

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

将名称键重命名为first_name:

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

现在,这个对象是:

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

5
我认为从概念上讲,最好将旧对象(来自Web服务的对象)保持不变,并在新对象中放置所需的值。我假设您在某个时候会提取特定字段,无论是在客户端还是服务器上。您选择使用与Web服务相同但只是小写的字段名称并不真正改变这一事实。因此,我建议采取以下措施:
var myObj = {
    field1: theirObj.FIELD1, 
    field2: theirObj.FIELD2,
    (etc)
}

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

如果您不想这么做,并且您只需要支持特定的浏览器,您也可以使用新的getter方法来返回“uppercase(field)”:请参阅http://robertnyman.com/2009/05/28/getters-and-setters-with-javascript-code-samples-and-demos/以获取更多信息。

编辑:

令人难以置信的是,在我的工作中,至少在我的FF3.5上,这也快了将近两倍。请参见:http://jsperf.com/spiny001


非常感谢您的努力,但使用案例不操作静态对象,因为它们的结构和深度是未知的。因此,如果可能的话,我想坚持问题的原始范围。 - Jean Vincent
现在考虑一下你在创建垃圾时必须执行的垃圾回收,每一次都会产生...单独...查看一下这是最低效的方式..还要更改第一级属性的值,看看它是否会与其他地方对旧值的引用同步 :) - zergski

5

如果您想保留迭代顺序(插入顺序),这里提供了一个建议:

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
}

5

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

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

4
请使用[编辑]链接来解释这段代码的工作原理,而不仅仅给出代码,因为解释更有可能帮助未来的读者。另请参阅[答案]。来源 - Jed Fox
我同意。虽然它没有明确回答问题,但作为重命名对象中所有键的解决方案,它帮助我完成了工作。也许我错过了主题... - Tudor Morar

4

此页面列出的一些解决方案具有一些副作用:

  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。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接