2011-01-10 17 views
160

JavaScriptオブジェクトのキーの名前を変更するための賢明な(つまり最適化された)方法はありますか?JavaScript:オブジェクトの名前を変更するキー

非最適化された方法は、次のようになります。

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

あなたは "最適化" とはどういう意味ですか?私はそれ以上は簡潔ではないと思う。組み込み操作の名前変更はありません。 – Pointy

+7

これですべてが得られます。私は自分のアプリケーションで他のことについて心配しています。そしてbtw、あなたは配列ではなくオブジェクトを扱っています。 JavaScriptには(厳密には)連想配列はありません。 –

+0

最適化は、より速く、よりコンパクトに、またはより読みやすくなります。 –

答えて

80

あなたは、関数の中で仕事をラップし、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特定

私は構文は、この複雑ではありませんでしたいが、それはより多くの制御を持っ間違いなくいいです。

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

@ChaosPandionは申し訳ありません試みることができるあなたのNode.js使用している場合も:) –

+1

@Ivo - なぜプロトタイプの拡張が悪いと感じるのか説明できますか?プロトタイプは、赤ちゃんを拡張するために作られました! – ChaosPandion

+0

@ChaosPandion Prototype.jsは素晴らしい例です** **なぜそれが悪いのか、その開発者が認めているのは悪いライブラリのために使用すること。 –

2

私はそれがあるとして、単に古いオブジェクト(Webサービスからの1)を残すようにビューの概念的な観点から良いだろうと言うと、あなたは新しいオブジェクトに必要な値を入れてしまうでしょう。私はあなたが特定のフィールドを抽出することを前提としています。 Webサービスからのフィールド名と同じフィールド名を使用することを選択したという事実は、小文字だけで実際には変更されません。もちろん、

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

私は本当ではないかもしれない、ここで仮定のすべての種類を、作ってるんだ:だから、私はこのような何かをお勧めします。これはあなたには当てはまりませんが、それが遅すぎる場合(それはどうですか?私はテストしませんでしたが、フィールドの数が増えるにつれてその差が小さくなると思います)、

これをやりたくない場合に、特定のブラウザのみをサポートする必要がある場合は、新しいゲッターを使用して「大文字(フィールド)」も返すことができます。http://robertnyman.com/2009/05/28/getters-and-setters-with-javascript-code-samples-and-demos/とそのページのリンクを参照してください。

EDIT:

信じられないほど、これは少なくとも仕事で私のFF3.5で、ほぼ倍もの速さです。参照:http://jsperf.com/spiny001

+0

ありがとう、あなたの努力に感謝します。しかし、ユースケースは、静的オブジェクトの構造と深さが分からないため、静的オブジェクトを操作しません。可能であれば、私はその質問の元の範囲に固執したいと思います。 –

109

だろうこれを行うの最も完全な(そして正しい)道を、私は信じている:

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

このメソッドは、名前を変更したプロパティが同一のオリジナルのものに動作することを保証します。

また、これを関数/メソッドにラップしてObject.prototypeに入れることは、あなたの質問とは無関係です。

+0

これはすべてのプロパティを保持しているだけでなく、優れたES5専用ソリューションです。したがって、これは「最適化」されていませんが、ES5ではより正確です。 –

+3

はwriting_things_with_underscoresへのいくつかの懐疑的な態度で支持されたが、それは疑問を呈する人によるものだった。これは私の見解では正しい応答です。 –

+3

私はあなたに+50000を与えることを望みます –

4

私はこのような何かをしたい:

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

静的キーを「未定義」に変換しないソリューションの更新版を ここに作成しました: https://gist.github.com/diasdavid/f8997fb0bdf4dc1c3543 それでも、JSONオブジェクトのいくつかのレベル(ネストされたキーを再配置)のアイデアを再マッピングしたいという問題は解決していませんか? –

3

個人的には、余分な重いプラグインや車輪を実装せずに、オブジェクト内のキーの名前を変更するための最も効果的な方法は:

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

object = JSON.parse(str); 

あなたはまた、それをラップすることができますあなたのオブジェクトが無効な構造を持っている場合はtry-catchにあります。完璧に動作します:)

+11

varオブジェクト= {b: '123'、 'c': 'bbb'}; var str = JSON.stringify(object); str = str.replace(/ b/g、 'newKey'); str = str.replace(/ c/g、 'newKey2'); オブジェクト= JSON.parse(文字列); – BlondinkaBrain

+3

これはどのように速度が比較されますか? – mix3d

+15

また、データ値のどこかに潜在的な問題が発生するのは、古いキー名と同じ文字列です。 – mix3d

0

これは正確にキーの名前を変更するよりよい解決策を与えるものではありませんが、それらに含まれるデータを変異されていないが、それはオブジェクト内のすべてのキーの名前を変更するために迅速かつ簡単なES6の方法を提供します。

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

あなたが行ったこととその理由を詳しく教えてください。 – empiric

+3

[編集]リンクを使用して、このコードの仕組みを説明してください。将来の読者の説明に役立つように、コードを記述するだけではありません。 [回答]も参照してください。 [ソース](http://stackoverflow.com/users/5244995) –

+0

私は同意します。それは具体的に質問に答えることはありませんが、それはオブジェクトのすべてのキーの名前を変更するためのソリューションとして仕事を完了するのに役立ちました。たぶん私は話題を逃した.. –

12

場合、誰かがプロパティのリストの名前を変更する必要があります:

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

これは、私のユースケースのためにうまくいった答えを受け入れる必要があります。私は不要な文字列で国名の前に付いていたAPI応答を変換しなければなりませんでした。オブジェクトをキーの配列に変換し、各キーを部分文字列メソッドでマップし、元のキーでインデックスされた新しいキーと値を持つ新しいオブジェクトを返しました –

5

私はちょうどES6(ES2015)方法を使用したいと思います!私たちが時代に追いつい必要

const old_obj = { 
 
    k1: `111`, 
 
    k2: `222`, 
 
    k3: `333` 
 
}; 
 
console.log(`old_obj =\n`, old_obj); 
 
// {k1: "111", k2: "222", k3: "333"} 
 

 

 
/** 
 
* @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 screen shortcut

+0

不正なオブジェクトを新しい再構築されたオブジェクトに変換する場合は、 – Daenarys

+0

いいですが、const {k1:kA、k2:kB、k3:kC} = old_objで十分ですか?普及する必要はありません(old_objのコピーが必要な場合を除きます)。 – Hans

関連する問題