JavaScriptオブジェクトのキーの名前を変更する賢い(つまり最適化された)方法はありますか?
最適化されていない方法は次のとおりです。
o[ new_key ] = o[ old_key ];
delete o[ old_key ];
JavaScriptオブジェクトのキーの名前を変更する賢い(つまり最適化された)方法はありますか?
最適化されていない方法は次のとおりです。
o[ new_key ] = o[ old_key ];
delete o[ old_key ];
回答:
これを行う最も完全な(そして正しい)方法は次のようになると思います。
if (old_key !== new_key) {
Object.defineProperty(o, new_key,
Object.getOwnPropertyDescriptor(o, old_key));
delete o[old_key];
}
このメソッドは、名前が変更されたプロパティが元のプロパティと同じように動作することを保証します。
また、これを関数/メソッドにラップして入れる可能性Object.prototype
は、あなたの質問とは無関係であるように私には思えます。
if (old_key !== new_key)
へ: if (old_key !== new_key && o[old_key])
作業を関数にラップして、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;
}
}
);
Object.defineProperty
。
hasOwnProperty
プロパティのチェックとfor ... in
ループ内で常にを使用することが適切な方法である場合、Objectを拡張することが重要なのはなぜですか?
ソースオブジェクトを変更する場合、ES6は1行で変更できます。
delete Object.assign(o, {[newKey]: o[oldKey] })[oldKey];
または、新しいオブジェクトを作成する場合は2行。
const newObject = {};
delete Object.assign(newObject, o, {[newKey]: o[oldKey] })[oldKey];
[]
周りに角括弧があるのnewKey
ですか?ソリューションは実際にそれなしで動作します。
プロパティのリストの名前を変更する必要がある場合:
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"}
my_object_property
していましたがmyObjectProperty
、私のプロパティが一語の場合、キーは削除されました。+1
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"}
データを変更したくない場合は、この関数を検討してください...
renameProp = (oldProp, newProp, {[oldProp]:old, ...others}) => ({
[newProp]: old,
...others
})
Yazeed Bzadoughによる徹底した説明 https://medium.com/front-end-hacking/immutably-rename-object-keys-in-javascript-5f6353c7b6dd
ここでの答えのほとんどは、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] }
}
});
ソリューションは、古いエントリの代わりに新しいエントリを追加することで、エントリの順序を維持します。
あなたは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};
個人的に、余分なプラグインやホイールを実装せずにオブジェクトのキーの名前を変更する最も効果的な方法:
var str = JSON.stringify(object);
str = str.replace(/oldKey/g, 'newKey');
str = str.replace(/oldKey2/g, 'newKey2');
object = JSON.parse(str);
try-catch
オブジェクトに無効な構造がある場合は、それをラップすることもできます。完璧に動作します:)
'a'
する{ a: 1, aa: 2, aaa: 3}
か、オブジェクトの名前を変更するか、循環参照で試してください。
私はこのようなことをします:
function renameKeys(dict, keyMap) {
return _.reduce(dict, function(newDict, val, oldKey) {
var newKey = keyMap[oldKey] || oldKey
newDict[newKey] = val
return newDict
}, {})
}
古いオブジェクト(Webサービスからのもの)をそのままにして、必要な値を新しいオブジェクトに入れる方が、概念的な観点からは良いと思います。とにかく、クライアントではなくても、少なくともサーバーで、特定のフィールドをとにかく抽出することを想定しています。Webサービスのものと同じで小文字のみのフィールド名を使用することを選択したという事実は、実際にはこれを変更しません。だから、私はこのようなことをすることをお勧めします:
var myObj = {
field1: theirObj.FIELD1,
field2: theirObj.FIELD2,
(etc)
}
もちろん、ここではあらゆる種類の仮定を行っていますが、そうではない場合もあります。これが当てはまらない場合、または遅すぎる場合(そうですか?私はテストしていませんが、フィールドの数が増えるにつれて差が小さくなると思います)、これはすべて無視してください:)
これを実行せず、特定のブラウザーのみをサポートする必要がある場合は、新しいゲッターを使用して「uppercase(field)」も返すことができます。http://robertnyman.com/2009/05/28を参照してください。 / getters-and-setters-with-javascript-code-samples-and-demos /および詳細については、そのページのリンク。
編集:
信じられないことに、これは少なくとも私の仕事中のFF3.5では、ほぼ2倍の速さです。参照:http : //jsperf.com/spiny001
これはキーの名前を変更するためのより良いソリューションを正確に提供するわけではありませんが、含まれているデータを変更せずにオブジェクトのすべてのキーの名前を変更するすばやく簡単なES6の方法を提供します。
let b = {a: ["1"], b:["2"]};
Object.keys(b).map(id => {
b[`root_${id}`] = [...b[id]];
delete b[id];
});
console.log(b);
このページにリストされているソリューションの一部には、いくつかの副作用があります。
以下は、キーの位置を同じ場所に保ち、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は、strictモードのforEachをサポートしない場合があります
これは、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);
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' };