Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there an efficient way to do a case-insensitive JavaScript object property name lookup? [duplicate]

There is a certain object I have where the exact case of the properties is not known ahead of time. For example, a property name might be "AbC" or "Abc" or "abc", etc.

I do, however, know that only one exists. That is I know there can't be both a property "AbC" and also a property "abc".

The property name itself is case-sensitive. So if it is stored as theObject.Abc and I lookup theObject.abc I won't find the property.

In my object there might be 1,000 such properties.

It would be, possible, but inefficient, if each time I wanted to do a lookup I compared the lower-case value of the property I want to find against the lower-case value of the property names, like this:

propertyName = inputValue.toLowerCase();
for (var i in theObject) {
   if (propertyName == i.toLowerCase()); // found a matching property name
}

Does anybody know a cleverer way of doing this?

For reasons it would take too long to explain, I cannot just recreate the object and make all the properties lower-case. I do realize if that was possible I could just find

theObject['inputValue'.toLowerCase()]

directly. But as I said, I can't. The property names in theObject are what they are and they can't be changed. Asking me why would be a huge digression from the problem at hand. Please take my word for it that theObject is stuck with the property names it has.

Does anybody know an efficient way of doing a case-insensitive property name lookup in a situation like this?

like image 346
Doug Lerner Avatar asked Feb 05 '16 06:02

Doug Lerner


3 Answers

And going even further than Sigfried:

var theObject = {aBc: 1, BBA: 2, CCCa: 4, Dba: 3};

var lcKeys = Object.keys (theObject).reduce (
                          function (keys, k) { keys[k.toLowerCase()] = k; 
                                               return keys }, {});

function getValue (key) { return theObject[lcKeys[key.toLowerCase ()]] }

console.log (getValue ('abc'));
console.log (getValue ('Dba'));
like image 91
HBP Avatar answered Oct 19 '22 01:10

HBP


Building off Jelly's example, but maybe more efficient or easier to understand:

 var theObject = {aBc: 1, BBA: 2, CCCa: 4, Dba: 3};
 var theKeys = Object.getOwnPropertyNames(theObject);
 var lookup = {};
 theKeys.forEach(function(key) {
     lookup[key.toLowerCase()] = key;
 });

 var getPropValue = function(prop){
     return lookup[prop.toLowerCase()];
 }
 console.log(getPropValue('abc'))
 console.log(getPropValue('Dba'))
like image 38
Sigfried Avatar answered Oct 18 '22 23:10

Sigfried


As you say, I don't think you want to the loop the Object way.And for you opinion,I thought a way, that's more effective and easy, and it don't loop anything.

let's see the fiddle:

https://fiddle.jshell.net/skgkLnx9/

here is the example:

var theObject = {aBc: 1, BBA: 2, CCCa: 4, Dba: 3};
// if your env is < ES5, you can use a polyfill( like underscore or lodash provided `_.keys` method )
var theKeys = Object.getOwnPropertyNames(theObject).toString();
// or var theKeys = Object.keys(theObject);

var getPropValue = function(prop){
    var match = new RegExp(prop, 'i').exec(theKeys);
  return match && match.length > 0 ? theObject[match[0]] : '';
}

console.log(getPropValue('abc'))

console.log(getPropValue('Dba'))

I also get your consider about the large data you have.I also use my code to test a Object that have 500 property it's can directly return.Although when it very very large, it possible have some memory issue, I think this can give you an idea about resolve that.

wish could help you :)

like image 3
Jelly Avatar answered Oct 19 '22 01:10

Jelly