84

私は思いついた

function keysToLowerCase (obj) {
  var keys = Object.keys(obj);
  var n = keys.length;
  while (n--) {
    var key = keys[n]; // "cache" it, for less lookups to the array
    if (key !== key.toLowerCase()) { // might already be in its lower case version
        obj[key.toLowerCase()] = obj[key] // swap the value to a new lower case key
        delete obj[key] // delete the old key
    }
  }
  return (obj);
}

しかし、v8がそれでどのように動作するかはわかりません。たとえば、他のキーを実際に削除するのでしょうか、それとも参照のみを削除し、ガベージコレクターが後で私を噛むのでしょうか。

また、私はこれらのテストを作成しました。それらがどのように一致するかを確認できるように、そこに回答を追加していただければ幸いです。

編集1: どうやら、テストによると、キーがすでに小文字であるかどうかを確認しないと高速になりますが、それを除けば、これを無視して新しい小文字のキーを作成するだけで、より雑然としたものになりますか?ガベージコレクターはこれに満足しますか?

4

20 に答える 20

82

私が思いついた最速の方法は、新しいオブジェクトを作成する場合です

var key, keys = Object.keys(obj);
var n = keys.length;
var newobj={}
while (n--) {
  key = keys[n];
  newobj[key.toLowerCase()] = obj[key];
}

私はあなたに決定的な答えを与えるためにv8の現在の内部の働きに十分に精通していません。数年前、開発者がオブジェクトについて話しているビデオを見ました。IIRCは参照を削除するだけで、ガベージコレクターに処理させます。でも何年も前だったので、あの時だったとしても、今はそうなくてもいいです。

後で噛みますか?それはあなたがしていることに依存しますが、おそらくそうではありません。短命のオブジェクトを作成することは非常に一般的であるため、コードはそれを処理するように最適化されます。しかし、すべての環境には限界があり、多分それはあなたを噛むでしょう。実際のデータでテストする必要があります。

于 2012-09-22T04:07:38.000 に答える
39

Lo-Dash.transformを次のように使用します。

var lowerObj = _.transform(obj, function (result, val, key) {
    result[key.toLowerCase()] = val;
});
于 2014-08-13T15:23:37.203 に答える
36

個人的には、次を使用します。

let objectKeysToLowerCase = function (origObj) {
    return Object.keys(origObj).reduce(function (newObj, key) {
        let val = origObj[key];
        let newVal = (typeof val === 'object') ? objectKeysToLowerCase(val) : val;
        newObj[key.toLowerCase()] = newVal;
        return newObj;
    }, {});
}

簡潔で、ネストされたオブジェクトを処理するために再帰し、元のオブジェクトを変更するのではなく、新しいオブジェクトを返します。

私の限られたローカル テストでは、この関数は現在リストされている他の再帰的ソリューションよりも高速です (修正後)。他のものと比較してベンチマークしたいのですが、jsperf は現在ダウンしています (???)。

また、ES5.1 で書かれているため、MDN のドキュメントによると、FF 4 以降、Chrome 5 以降、IE 9.0 以降、Opera 12 以降、Safari 5 以降 (ほぼすべて) で動作するはずです。

勝利のためのバニラJS。

このすべてのガベージ コレクションの側面についてはあまり心配しません。古いオブジェクトへのすべての参照が破棄されると、それはGCになりますが、新しいオブジェクトは基本的にすべてのプロパティを参照するため、そうではありません。

関数、配列、または正規表現は、参照によって「コピー」されます。メモリに関しては、ほとんど (すべて?) の最新の JS エンジンはstring interningを使用しているため、このプロセスでは文字列でさえ複製されません。元の構造を形成していた Numbers、Booleans、および Objects だけが GC の対象として残されていると思います。

オリジナルに同じ小文字表現のプロパティが複数ある場合、このプロセス (のすべての実装) は値を失うことに注意してください。すなわち:

let myObj = { xx: 'There', xX: 'can be', Xx: 'only', XX: 'one!' };
console.log(myObj);
// { xx: 'There', xX: 'can be', Xx: 'only', XX: 'one!' }

let newObj = objectKeysToLowerCase(myObj);
console.log(newObj);
// { xx: 'one!' }

もちろん、これがまさにあなたが望むものである場合もあります。

2018-07-17 更新

元の関数が配列ではうまく機能しないことに気付いた人もいます。これは、拡張された、より回復力のあるバージョンです。配列を正しく再帰し、初期値が配列または単純な値の場合に機能します。

let objectKeysToLowerCase = function (input) {
    if (typeof input !== 'object') return input;
    if (Array.isArray(input)) return input.map(objectKeysToLowerCase);
    return Object.keys(input).reduce(function (newObj, key) {
        let val = input[key];
        let newVal = (typeof val === 'object') && val !== null ? objectKeysToLowerCase(val) : val;
        newObj[key.toLowerCase()] = newVal;
        return newObj;
    }, {});
};
于 2016-12-10T05:45:24.533 に答える
5

私のテストでは、 forEach を使用する方が少し速いようです-元の参照がなくなっているため、新しい参照を削除すると、GCの範囲内になります

function keysToLowerCase(obj){
    Object.keys(obj).forEach(function (key) {
        var k = key.toLowerCase();

        if (k !== key) {
            obj[k] = obj[key];
            delete obj[key];
        }
    });
    return (obj);
}

var O={1:1,2:2,t3:3,4:4,5:5,6:{a:1,b:2,c:3,D:4,E:5}}; keysToLowerCase(O);

/* 戻り値: (オブジェクト) */

{
    five:5,
    four:4,
    one:1,
    six:{
        a:1,
        b:2,
        c:3,
        D:4,
        E:5
    },
    three:3,
    two:2
}
于 2012-09-22T01:13:08.880 に答える
3

すべてのjsonキーを小文字に変換する最も簡単なソリューションは次のとおりです。

let o = {"Account_Number   ":"0102301", "customer_NaME":"name"}

o = Object.keys(o).reduce((c, k) => (c[k.toLowerCase().trim()] = o[k], c), {})

console.log(o)
于 2020-03-26T08:59:48.087 に答える
0

大文字と小文字を一度だけ下げて、lowKeyvarに格納することを検討してください。

function keysToLowerCase (obj) {
  var keys = Object.keys(obj);
  var n = keys.length;
  var lowKey;
  while (n--) {
    var key = keys[n];
    if (key === (lowKey = key.toLowerCase()))
    continue

    obj[lowKey] = obj[key]
    delete obj[key]

  }
  return (obj);
}
于 2012-09-22T00:30:29.177 に答える