web-dev-qa-db-ja.com

JavaScript:オブジェクト名変更キー

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

最適化されていない方法は次のようになります。

o[ new_key ] = o[ old_key ];
delete o[ old_key ];
221
Jean Vincent

これを行うための最も完全な(そして正しい)方法は次のようになります。

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

このメソッドは、名前が変更されたプロパティ同じ動作をするを元のプロパティに確実にします。

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

157
Valeriu Paloş

作業を関数にラップして、それを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;
        }
    }
);
87
ChaosPandion

ソースオブジェクトを変更している場合、ES6はそれを1行で実行できます。

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

新しいオブジェクトを作成したい場合は2行です。

const newObject = {};
delete Object.assign(newObject, o, {[newKey]: o[oldKey] })[oldKey];
40
nverba

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

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

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 screen shortcut

17
xgqfrms-gildata

データを変更したくない場合は、この機能を検討してください。

renameProp = (oldProp, newProp, {[oldProp]:old, ...others}) => ({
    [newProp]: old,
    ...others
})

Yazeed Bzadoughによる徹底的な説明 https://medium.com/front-end-hacking/immutably-rename-object-keys-in-javascript-5f6353c7b6dd


6
Mulhoon

オブジェクト分割と拡散演算子を使用したバリエーション

    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};
5
Jeff Lowery

私はこのようなことをしたいと思います:

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

概念的な観点からは、古いオブジェクト(Webサービスからのもの)をそのままにして、必要な値を新しいオブジェクトに入れる方が良いと思います。私はあなたが、クライアント上ではなくて、それから少なくともサーバー上では、とにかく、ある時点または別の場所で特定のフィールドを抽出していると思います。 Webサービスのフィールド名と同じフィールド名を使用することを選択したという事実は、実際にはこれを変更しません。だから、私はこのようなことをすることをお勧めします:

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

もちろん、ここではあらゆる種類の仮定をしていますが、そうではないかもしれません。これがあなたに当てはまらない場合、または遅すぎる場合(それはテストしていませんが、フィールドの数が増えるにつれて違いは小さくなると思います)、これをすべて無視してください:)

あなたがこれをしたくない、そしてあなたが特定のブラウザだけをサポートする必要があるならば、あなたはまた「uppercase(field)」を返すために新しいゲッターを使うことができます: http://robertnyman.com/2009詳細については、/ 05/28/javascript-code-samples-and-demos / およびそのページのリンクを参照してください。

編集:

信じられないかもしれませんが、これはほぼ2倍の速さです。少なくとも私のFF3.5の仕事では。参照してください: http://jsperf.com/spiny001

3
Spiny Norman

このページにリストされている解決策のいくつかはいくつかの副作用があります。

  1. オブジェクト内のキーの位置に影響を与え、それを下に追加します(これが重要な場合)。
  2. iE9 +では動作しません(これがあなたにとって重要な場合)

これは、キーの位置を同じ場所に保ち、IE 9以降と互換性のある解決策ですが、新しいオブジェクトを作成する必要があり、最速の解決策ではない場合があります。

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をサポートしないかもしれません

2
Jasdeep Khalsa

あなたは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>
2
Penny Liu

これは、名前を変更したキーを使って新しいオブジェクトを作成する例です。

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

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

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

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

object = JSON.parse(str);

オブジェクトに無効な構造がある場合は、try-catchでラップすることもできます。完璧に動作します:)

1
Novitoll

これはキーの名前を変更するためのより良い解決策を正確には与えませんが、それは含まれているデータを変えずにオブジェクト内のすべてのキーの名前を変更する素早く簡単なES6方法を提供します。

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

ここでの回答のほとんどは、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] }
  }
});

このソリューションは、古いエントリの代わりに新しいエントリを追加することによってエントリの順序を保持します。

0
afalak

これは私が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);
0
Jasp402

私の考えでは、あなたのやり方は最適化されています。しかし、鍵の順序が変わることになります。新しく作成されたキーは最後に追加されます。キーの順序に頼るべきではないことは知っていますが、それを保存する必要がある場合は、すべてのキーを調べて新しいオブジェクトを1つずつ作成し、その過程で問題のキーを置き換える必要があります。

このような:

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;
0
Tomas M