Javascript: Quickly lookup value in object (like we can with properties)
Solution 1
It's more efficient to loop just once beforehand to create a reverse map:
var str = "Hello World!",
output = '',
map = {
"s":"d", "m":"e",
"e":"h", "x":"l",
"z":"o", "i":"r",
"a":"w", "o":"!",
"-":" "
},
reverseMap = {}
for (j in map){
if (!Object.prototype.hasOwnProperty.call(map, j)) continue
reverseMap[map[j]] = j
}
output = str.replace(/./g, function(c){
return reverseMap[c] || reverseMap[c.toLowerCase()].toUpperCase()
})
console.log(output)
Instead of doing str.length * map.length
, you'll do map.length + str.length
operations.
Solution 2
A reverse encoder would make more sense, but you can write a replace function without all the hasOwnProperty etc.tests.
var str= 'Hello World!',
obj={
's':'d',
'm':'e',
'e':'h',
'x':'l',
'z':'o',
'i':'r',
'a':'w',
'o':'!',
'-':' '
}
str= str.replace(/./g, function(w){
for(var p in obj){
if(obj[p]=== w) return p;
if(obj[p]=== w.toLowerCase()) return p.toUpperCase();
};
return w;
});
returned value: (String) Emxxz-Azixso
Solution 3
You can create a reversed version of the mapping programmatically (instead of by hand) and use it instead.
var rev = {}
for (key in obj)
rev[obj[key]] = key
Marcus Hughes
Updated on June 15, 2022Comments
-
Marcus Hughes almost 2 years
I have an object that has pairs of replacement values used for simple encoding / decoding (not for security, just for a convenience; too complicated to explain it all here). It's in the form
var obj = {x: y, x: y, ... };
where 'x' is the value when encoded and 'y' is the decoded value.
Decoding is simple: I loop through the characters of the string, and look up the
charAt(i)
value in the object via brackets:obj[ str.charAt(i) ]
. (I'm leaving out the check to see whether we need an uppercase or lowercase version (all key/values in the object are lowercase), but that's simple enough.)To encode, I of course have to look for the value in the object, rather than the property. Currently, I'm looping through the properties with a
for ... in ...
loop and checking the values against thecharAt(i)
value. My current code is:var i, j, output = '', str = 'Hello World!', obj = {'s':'d', 'm':'e', 'e':'h', 'x':'l', 'z':'o', 'i':'r', 'a':'w', 'o':'!', '-':' '}; for (i = 0; i < str.length; i++) { for (j in obj) { if (Object.prototype.hasOwnProperty.call(obj, j) && Object.prototype.propertyIsEnumerable.call(obj, j)) { if (obj[j] === str.charAt(i)) { output += j; break; } else if (obj[j].toUpperCase() === str.charAt(i)) { output += j.toUpperCase(); break; } } } } alert(output);
I innately feel like there should be a more efficient way of doing this. (Of course having a reversed object, {y: x}, is an option. But not a good one.) Is this the best way, or is there a better? In essence, I'd love to be able to do
var prop = obj[value]
just like I can dovar value = obj[prop]
.