Was ist der beste (effizienteste) Weg, um alle Schlüssel eines Objekts in Kleinbuchstaben umzuwandeln?

Lesezeit: 7 Minuten

Benutzer-Avatar
João Pinto Jerónimo

Ich bin darauf gekommen

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

Aber ich bin mir nicht sicher, wie sich v8 damit verhalten wird, wird es zum Beispiel wirklich die anderen Schlüssel löschen oder werden nur Referenzen gelöscht und der Garbage Collector wird mich später beißen?

Außerdem habe ich erstellt diese Prüfungenich hoffe, Sie könnten Ihre Antwort dort hinzufügen, damit wir sehen können, wie sie zusammenpassen.

BEARBEITEN 1:
Anscheinend ist es den Tests zufolge schneller, wenn wir nicht prüfen, ob der Schlüssel bereits in Kleinbuchstaben geschrieben ist, aber da er schneller ist, wird er mehr Unordnung schaffen, wenn er dies ignoriert und einfach neue Kleinbuchstaben erstellt? Wird der Garbage Collector damit zufrieden sein?

  • Können Sie ein neues Objekt erstellen, anstatt das vorhandene zu ändern? Sie würden alle Löschungen überspringen.

    – Jason Orendorff

    22. September 2012 um 0:32 Uhr

  • Ich denke, Ihr Code ist vernünftig, wie er ist. “Es ist schneller, wenn wir nicht prüfen, ob der Schlüssel bereits in Kleinbuchstaben ist, aber … wird es mehr Unordnung schaffen, wenn dies ignoriert und nur neue Kleinbuchstaben erstellt werden?” – Dieser Code funktioniert nicht wirklich (er löscht am Ende alle Schlüssel, die bereits Kleinbuchstaben waren), also spielt es wirklich keine Rolle, wie schnell er ist …

    – nnnnn

    22. September 2012 um 0:33 Uhr


  • @JasonOrendorff anscheinend ist es langsamer und es würde jedes Mal ein unnötiges Objekt erstellen, und der Garbage Collector wäre damit nicht zufrieden …

    – João Pinto Jerónimo

    22. September 2012 um 0:40 Uhr

  • @JoãoPintoJerónimo Was Sie in Ihren Geschwindigkeitstests sehen, ist, dass der Code Tausende Male auf demselben Objekt ausgeführt wird. Nach einmaligen Testläufen gibt es natürlich keine Arbeit mehr; Alle Tasten sind bereits Kleinbuchstaben. Wenn Sie es testen, indem Sie viele Objekte mit vielen Schlüsseln erstellen: jsperf.com/object-keys-to-lower-case/7 dann sind alle drei Implementierungen dramatisch langsamer, aber das Erstellen eines neuen Objekts ist sowohl in Firefox als auch in Chrome etwas schneller.

    – Jason Orendorff

    22. September 2012 um 3:28 Uhr

  • Oh, ich verstehe @JasonOrendorff … Ich werde die Tests noch einmal überarbeiten

    – João Pinto Jerónimo

    22. September 2012 um 3:34 Uhr

Benutzer-Avatar
etwas

Das am schnellsten Ich komme mit, wenn Sie ein neues Objekt erstellen:

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

Ich bin mit dem aktuellen Innenleben von v8 nicht vertraut genug, um Ihnen eine endgültige Antwort zu geben. Vor ein paar Jahren habe ich ein Video gesehen, in dem die Entwickler über Objekte gesprochen haben, und IIRC wird nur die Referenzen löschen und den Garbage Collector sich darum kümmern lassen. Aber es ist Jahre her, also selbst wenn es damals so war, muss es jetzt nicht so sein.

Wird es dich später beißen? Es hängt davon ab, was Sie tun, aber wahrscheinlich nicht. Es ist sehr üblich, kurzlebige Objekte zu erstellen, sodass der Code dafür optimiert ist, damit umzugehen. Aber jede Umgebung hat ihre Grenzen, und vielleicht beißt sie dich. Sie müssen mit tatsächlichen Daten testen.

  • Dies ist die beste Antwort, aber @JasonOrendorff verdient auch Anerkennung dafür.

    – João Pinto Jerónimo

    22. September 2012 um 22:28 Uhr

  • Ich denke, das braucht eine var vor dem key = keys[n] ?

    – Andreas Ferrier

    6. Juni 2013 um 15:52 Uhr

  • @AndrewFerrier Richtig. Fest.

    – etwas

    23. Juli 2013 um 21:27 Uhr

  • Dies macht nur eine Ebene, wenn Sie etwas wie {A:1, B : { C: 2 }} haben. A und B würden geändert, aber nicht C

    – Michael Warner

    17. Januar 2017 um 21:31 Uhr

  • @MichaelWarner Das ist richtig, es berührt nur die Tasten in dem Objekt, das Sie ihm geben, und berührt die Kinder nicht. Darum ging es in der Frage. Es sieht so aus, als wollten Sie eine tiefe Kopie machen, aber das ist ein dunkler tiefer Kaninchenbau …

    – etwas

    18. Januar 2017 um 3:20 Uhr

Benutzer-Avatar
Yves M.

Verwenden Object.fromEntries (ES10)

Native und unveränderliche Lösung mit dem neuen Object.fromEntries Methode:


const newObj = Object.fromEntries(
  Object.entries(obj).map(([k, v]) => [k.toLowerCase(), v])
);

Bis zu dieser Funktion wird breit verfügbar Sie könnten es selbst mit dem folgenden definieren Polyfill:

Object.fromEntries = arr => Object.assign({}, ...Array.from(arr, ([k, v]) => ({[k]: v}) ));

Eine schöne Sache ist, dass diese Methode das Gegenteil von bewirkt Object.entriessodass Sie jetzt zwischen der Objekt- und der Array-Darstellung hin und her wechseln können.

Benutzer-Avatar
Kaleb

Ich würde verwenden Lo-Dash.transform so was:

var lowerObj = _.transform(obj, function (result, val, key) {
    result[key.toLowerCase()] = val;
});

  • Sie können jetzt verwenden Object.fromEntries um die gleiche Art von Transformation zu erreichen, aber nativ, mit Vanilla JavaScript

    – Yves M.

    10. März 2019 um 11:45 Uhr

  • @YvesM. wird von IE11 nicht unterstützt 🙁

    – Mosh-Feu

    16. April 2020 um 7:22 Uhr

Benutzer-Avatar
Molombie

Ich persönlich würde verwenden:

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;
    }, {});
}

Es ist prägnant, behandelt verschachtelte Objekte wieder und gibt ein neues Objekt zurück, anstatt das Original zu ändern.

In meinen begrenzten lokalen Tests ist diese Funktion schneller als die andere derzeit aufgeführte rekursive Lösung (einmal behoben). Ich würde es gerne mit den anderen vergleichen, aber jsperf ist im Moment nicht verfügbar (???).

Es ist auch in ES5.1 geschrieben, also sollte es laut den Dokumenten auf MDN in FF 4+, Chrome 5+, IE 9.0+, Opera 12+, Safari 5+ (also so ziemlich alles) funktionieren.

Vanilla JS für den Sieg.

Ich würde mir nicht allzu viele Gedanken über den Aspekt der Garbage Collection machen. Sobald alle Verweise auf das alte Objekt zerstört sind, werden es aber die GC’s sein Neu Das Objekt wird im Grunde immer noch auf alle seine Eigenschaften verweisen, also nicht.

Alle Funktionen, Arrays oder RegExp werden durch Verweis “kopiert”. In Bezug auf den Speicher werden selbst Strings durch diesen Prozess nicht dupliziert, da die meisten (alle?) modernen JS-Engines Benutzer sind string internieren. Ich denke, das lässt nur die Zahlen, Booleans und die Objekte, die die ursprüngliche Struktur bildeten, übrig, um GC’d zu werden.

Beachten Sie, dass (alle Implementierungen) dieses Prozesses Werte verlieren, wenn das Original mehrere Eigenschaften mit derselben Darstellung in Kleinbuchstaben hat. Dh:

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!' }

Natürlich ist das manchmal genau das, was Sie wollen.

Update 17.07.2018

Einige Leute haben bemerkt, dass die ursprüngliche Funktion mit Arrays nicht gut funktioniert. Hier ist eine erweiterte, widerstandsfähigere Version. Es wiederholt sich korrekt durch Arrays und funktioniert, wenn der Anfangswert ein Array oder ein einfacher Wert ist:

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;
    }, {});
};

ES6-Version:

Object.keys(source)
  .reduce((destination, key) => {
    destination[key.toLowerCase()] = source[key];
    return destination;
  }, {});

Benutzer-Avatar
Damian Grün

Der loDash/fp-Weg, ganz nett, da es im Wesentlichen ein Einzeiler ist

import {
mapKeys
} from 'lodash/fp'

export function lowerCaseObjectKeys (value) {
return mapKeys(k => k.toLowerCase(), value)
}

Benutzer-Avatar
Szymon Toda

Die Verwendung von forEach scheint in meinen Tests etwas schneller zu sein – und die ursprüngliche Referenz ist weg, sodass das Löschen der neuen sie in die Reichweite des gc bringt

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={ONE:1,two:2,tThree:3,FOUR:4,Five:5,SIX:{a:1,b:2,c:3,D:4,E:5}}; TastenToLowerCase(O);

/* Rückgabewert: (Objekt) */

{
    five:5,
    four:4,
    one:1,
    six:{
        a:1,
        b:2,
        c:3,
        D:4,
        E:5
    },
    three:3,
    two:2
}

  • Ich habe Ihre Funktion zur 9. Revision hinzugefügt: jsperf.com/object-keys-to-lower-case/9

    – João Pinto Jerónimo

    22. September 2012 um 1:17 Uhr

  • immer noch nicht schneller als meine … Die umgekehrte While-Schleife ist die schnellste Schleife in Javascript, siehe hier: jsperf.com/javascript-loop (Die umgekehrte While-Schleife ist schneller, aber die Ergebnisse zeigen eine andere Sache als die schnellste, möglicherweise von alten Browsern, die sie zuvor ausgeführt haben.)

    – João Pinto Jerónimo

    22. September 2012 um 1:22 Uhr

  • keine reine Funktion – Sie mutieren das Argument

    – Eugen Fidelin

    26. Oktober 2017 um 15:13 Uhr

1175850cookie-checkWas ist der beste (effizienteste) Weg, um alle Schlüssel eines Objekts in Kleinbuchstaben umzuwandeln?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy