JavaScript:对象重命名密钥

Jea*_*ent 255 javascript rename key object

是否有一种聪明的(即优化的)方法来重命名javascript对象中的键?

一种非优化的方式是:

o[ new_key ] = o[ old_key ];
delete o[ old_key ];
Run Code Online (Sandbox Code Playgroud)

Val*_*loş 175

我相信最完整(也是最正确)的做法是:

if (old_key !== new_key) {
    Object.defineProperty(o, new_key,
        Object.getOwnPropertyDescriptor(o, old_key));
    delete o[old_key];
}
Run Code Online (Sandbox Code Playgroud)

此方法可确保重命名的属性原始属性的行为相同.

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

  • 对writ_things_with_underscores持怀疑态度,但当然这是由于该人提出了问题.这是我认为的正确答案. (5认同)
  • 如果重要,我相信ES5的这种特殊用法是IE9和更新的解决方案. (3认同)
  • 我建议添加 o.old_key 存在的验证。更改:`if (old_key !== new_key)` 到:`if (old_key !== new_key && o[old_key])` (3认同)

Cha*_*ion 93

您可以将函数包装在函数中并将其分配给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;
};
Run Code Online (Sandbox Code Playgroud)

ECMAScript 5具体

我希望语法不是很复杂但是拥有更多控制权肯定很好.

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;
        }
    }
);
Run Code Online (Sandbox Code Playgroud)

  • @Ivo - 我同意这是冒险的,但如果我觉得它会导致更具表现力的代码,那么没有任何东西可以阻止我扩展原型.虽然我来自ECMAScript 5思维模式,你可以通过`Object.defineProperty`将属性标记为不可枚举. (5认同)
  • @ChaosPandion很抱歉,但我真的厌倦了错误的JS代码,我正在编写一本关于所有怪癖的指南(https://github.com/BonsaiDen/JavaScript-Garden)(包括你现在的那个)已修复),这可能会让我进入某种咆哮模式;)(现在删除了-1) (4认同)
  • @Ivo - 如果正确的做法是始终使用`hasOwnProperty`来检查属性并在`for ... in`循环中,那么为什么扩展Object会有关系呢? (3认同)
  • 这段代码有效,但需要注意的是,如果新的密钥名称已经存在,那么它的值将会被践踏:http://jsfiddle.net/ryurage/B7x8x/ (2认同)

nve*_*rba 60

如果您正在改变源对象,ES6可以在一行中完成.

delete Object.assign(o, {[newKey]: o[oldKey] })[oldKey];
Run Code Online (Sandbox Code Playgroud)

如果要创建新对象,可以使用两行.

const newObject = {};
delete Object.assign(newObject, o, {[newKey]: o[oldKey] })[oldKey];
Run Code Online (Sandbox Code Playgroud)

  • 尝试:删除 Object.assign(o, {newKey: o.oldKey }).oldKey; 对我来说效果很好 (7认同)
  • 注意:Object.assign 的使用仅进行浅复制。 (5认同)
  • 如果您的变量名称更冗长,这个答案会更强。 (3认同)
  • 为什么在`newKey`周围有方括号`[]`?该解决方案实际上无需解决该问题。 (2认同)
  • 好的-我知道了。这是ES6功能。对于像我这样偶然发现的其他人,[这里是一个很好的答案](/sf/ask/805592441/)。 (2认同)

pom*_*ber 34

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

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

用法:

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

  • 这应该是可以接受的答案,对我的用例很有用。我必须转换一个 API 响应,该响应在国家/地区名称前加上不必要的字符串。将 Object 转换为键数组,并使用 substring 方法映射到每个键,并返回一个具有新键和由原始键索引的值的新对象 (2认同)

pio*_*_cz 23

为每个键添加前缀:

const obj = {foo: 'bar'}

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

// altObj = {'x-foo': 'bar'}
Run Code Online (Sandbox Code Playgroud)

  • 我认为这是迄今为止最简单的答案,应该是公认的答案。我用它来小写所有键并用下划线替换空格。 (2认同)

xgq*_*ata 20

我想用这种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"}
Run Code Online (Sandbox Code Playgroud)

演示屏快捷方式

  • 好的,但我认为const {k1:kA,k2:kB,k3:kC,} = old_obj就足够了吗?无需传播(除非你想要old_obj的副本). (4认同)
  • 这需要更多的代码,效率会更低,并且会创建一个新对象。重命名属性意味着改变对象。新的并不总是更好。 (2认同)

Aay*_*rya 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"}]
Run Code Online (Sandbox Code Playgroud)

最好有一个新数组


Sub*_*bbU 12

另一种使用最强大的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"}
Run Code Online (Sandbox Code Playgroud)


Mul*_*oon 11

如果您不想变异数据,请考虑使用此功能...

renameProp = (oldProp, newProp, {[oldProp]:old, ...others}) => ({
    [newProp]: old,
    ...others
})
Run Code Online (Sandbox Code Playgroud)

Yazeed Bzadough的详尽解释 https://medium.com/front-end-hacking/immutably-rename-object-keys-in-javascript-5f6353c7b6dd



Jef*_*ery 8

使用对象解构和散布运算符的变体:

    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};
Run Code Online (Sandbox Code Playgroud)

  • 也许您可以解释一下这是做什么以及它是如何工作的? (2认同)

Pen*_*Liu 7

您可以尝试lodash _.mapKeys

var user = {
  name: "Andrew",
  id: 25,
  reported: false
};

var renamed = _.mapKeys(user, function(value, key) {
  return key + "_" + user.id;
});

console.log(renamed);
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
Run Code Online (Sandbox Code Playgroud)


Pab*_*blo 6

只需在您最喜欢的编辑器中尝试一下 <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
}
Run Code Online (Sandbox Code Playgroud)


Uma*_*ang 6

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

让我们考虑一下这个对象:

let obj = {"name": "John", "id": 1, "last_name": "Doe"}
Run Code Online (Sandbox Code Playgroud)

让我们将 name 键重命名为first_name:

let { name: first_name, ...rest } = obj;
obj = { first_name, ...rest }
Run Code Online (Sandbox Code Playgroud)

现在对象是:

{"first_name": "John", "id": 1, "last_name": "Doe"}
Run Code Online (Sandbox Code Playgroud)


Spi*_*man 5

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

var myObj = {
    field1: theirObj.FIELD1, 
    field2: theirObj.FIELD2,
    (etc)
}
Run Code Online (Sandbox Code Playgroud)

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

如果你不想这样做,而你只需要支持特定的浏览器,你也可以使用新的 getter 来返回“uppercase(field)”:见http://robertnyman.com/2009/05/28 /getters-and-setters-with-javascript-code-samples-and-demos/以及该页面上的链接以获取更多信息。

编辑:

令人难以置信的是,这几乎快了两倍,至少在我工作的 FF3.5 上是这样。见:http : //jsperf.com/spiny001


tld*_*ldr 5

我会做这样的事情:

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

  • 制作了解决方案的更新版本,该解决方案不会在此处将静态键转换为“未定义”:https://gist.github.com/diasdavid/f8997fb0bdf4dc1c3543不过,它仍然没有解决要在多个位置重新映射键的问题。 JSON对象的级别(重新映射嵌套键),想法? (3认同)

Nov*_*oll 5

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

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

object = JSON.parse(str);
Run Code Online (Sandbox Code Playgroud)

try-catch如果您的对象具有无效结构,您也可以将其包装起来。完美运行:)

  • 还遇到了数据值中某处与旧键名称相同的字符串的潜在问题。 (17认同)
  • 哎呀!var object = {b : '123', 'c' : 'bbb'}; var str = JSON.stringify(object); str = str.replace(/b/g, 'newKey'); str = str.replace(/c/g, 'newKey2'); 对象 = JSON.parse(str); (14认同)
  • 这与速度相比如何? (5认同)
  • 对于“完美”的某些定义,“完美运行”。尝试在 `{ a: 1, aa: 2, aaa: 3}` 中重命名 `'a'`,或者尝试使用字符串、数字或布尔值以外的任何值重命名对象,或者尝试使用循环引用。 (5认同)

Tud*_*rar 5

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

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

  • 请使用 [edit] 链接来解释此代码的工作原理,而不仅仅是给出代码,因为解释更有可能帮助未来的读者。另请参阅[答案]。[来源](http://stackoverflow.com/users/5244995) (4认同)

小智 5

这里的大多数答案都无法维持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] }
  }
});
Run Code Online (Sandbox Code Playgroud)

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


小智 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
}
Run Code Online (Sandbox Code Playgroud)