0

Normally, I would do it like this

if (key in obj) {
    //other stuff
}

But I don't actually know that they are capitalized the same. What's the best way to do this? I would rather not iterate through the whole array, calling .toLowercase on each key in the object, but is that the only option?

River Tam
  • 3,096
  • 4
  • 31
  • 51
  • 2
    possible duplicate of [Access JavaScript property case-insensitively?](http://stackoverflow.com/questions/12484386/access-javascript-property-case-insensitively) – talemyn Feb 18 '15 at 18:47
  • I guess that's not always safe - you can have multiple versions of a key (ex. `value` / `Value`) in one object. Simple lowercase is not enough in such a case. – rubikonx9 Feb 18 '15 at 18:50
  • You're right that it's not always safe. Fortunately, the data set is "careful" in this way. – River Tam Feb 18 '15 at 18:57
  • You could read the keys with `Object.keys`, then join the resulted array to a string and test the key with RegExp. – Teemu Feb 18 '15 at 18:59
  • @Teemu : interesting solution, but it gets hairy if I actually want to read the value from the object, which I do later as it happens. – River Tam Feb 18 '15 at 19:01
  • In the question there's key detection only ... Though you can return a matched value from methods using RegExp. – Teemu Feb 18 '15 at 19:02
  • You're right, which is why I said "as it happens". – River Tam Feb 18 '15 at 19:03

3 Answers3

5

Long Code But Faster

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

if (objArr.indexOf(key)!==-1) {
        //other stuff on obj
}

Short Code, Less Efficient

var objTemp = JSON.parse(JSON.stringify(obj).toLowerCase());

Now check in

if (key in objTemp) {
    //other stuff on obj
}
void
  • 36,090
  • 8
  • 62
  • 107
  • That looks like less code, but probably much less efficient if (like I have) the size of the keys are way smaller than the size of the values. – River Tam Feb 18 '15 at 18:48
  • Thanks. I think I'm going to go with something similar, but without the objTemp. So I'm just going to iterate through the keys (using `Object.keys(obj)`) and only change the parameter instead of the values of the object. – River Tam Feb 18 '15 at 18:55
  • In the faster way, I am not changing the the value of parameter. Its just key which i am converting to lower case. – void Feb 18 '15 at 18:57
  • So in my problem, I get a parameter (we'll call it `key` because we like confusing variable names) and an object with let's say 100 key/value pairs. With your solution, I have to convert and store 100 keys, as well as storing everything else in the object. With the solution I intend to use, I only have to change `key`, and that's all I have to store/change/copy. The object (which is huge) doesn't need a copy, whereas in yours it needs an objTemp which is almost identical. – River Tam Feb 18 '15 at 19:00
  • @void - please fix the line `if (objArr.indexOf(key)) {` to read `if (objArr.indexOf(key) !== -1) {`. – Alvin Thompson Feb 18 '15 at 21:18
  • I'm nit-picking now, but it should be `!==` and not `!=`. – Alvin Thompson Feb 18 '15 at 21:25
  • Yes, `!=` will work fine in this case, but it's considered bad practice to use `==` and `!=` when `===` and `!==` are better matches. Since the former will coerce types if necessary, it can lead to unexpected behavior and hard-to-find bugs. It will also generate an unnecessary warning in many IDEs/editors. – Alvin Thompson Feb 18 '15 at 21:36
  • Also keep in mind that this is an advice website. You may be advanced enough to know and avoid all the edge cases where `==` will get you into trouble, but you can't assume that about all the people who will look at this page for advice on how to accomplish this. It's best to set them on the right path so they stay out of avoidable problems. – Alvin Thompson Feb 18 '15 at 21:43
0

Presumably you don't know what the key-casing is because you're getting the objects from a 3rd party source, such as an AJAX call or other script resource load. You can interject a normalization method at that point and only have to loop once per object, making it a static overhead cost.

For example, define a method

function normalizeObjectKeys(obj) {
  for (key in obj) {
    obj[key.toUpperCase()] = foo[key];
    delete obj[key];
  }
}

Calling it like this in my Chrome javascript console seems to prove it works.

> var foo = { bar: "bar", baZ: "baZ" }
undefined
> foo
Object {bar: "bar", baZ: "baZ"}
> normalizeObjectKeys(foo)
undefined
> foo
Object {BAR: "bar", BAZ: "baZ"}

Then you always check for the uppercase version of the key. It's not pretty, and will collide if there are different cases of the same key (e.g. foo = {bar : "bar", Bar : "baz" } could wind up with either value of BAR), but it might suit your purposes. If you really need to know, you could check whether obj[key.toUpperCase] == undefined before setting the value and log an error or throw an exception.

Patrick M
  • 10,547
  • 9
  • 68
  • 101
0

Here's what you want:

function lowerCaseObjectKeys(object) {
  // clone the original object so that we don't modify its state
  const newObject = Object.assign({}, object);

  Object.keys(newObject).forEach((key) => {
    // if key is already lower-case, skip it & move on!
    if (key.toLowerCase() === key) {
      return;
    }

    // set a new, lower-cased key in newObject
    newObject[key.toLowerCase()] = newObject[key];
    // delete the original, non-lower-cased key (& value) from newObject
    delete newObject[key];
  });

  return newObject;
}

Now, you can fetch a value from an object, regardless of the casing of the key:

lowerCaseObjectKeys( yourObjectHere )[ 'lowercasedkeyhere' ];