Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I have a quite simple Javascript object, which I use as an associative array. Is there a simple function allowing me to get the key for an object, or do I have to iterate the object and find it out manually? In case there is a function, which is it?

share|improve this question
    
There is no such standard function to do this. If the mapping is truly bidirectional then it is trivial to construct a "flipped" map and index that. Otherwise a simple property-iterator (with a hasOwnProperty gaurd, perhaps) and an early-return hidden inside a function does just nicely... –  user166390 Mar 28 '12 at 12:27
    
How could this work if an object was referenced by more than one key? var o = []; var map = {first: o, second: o}. What would find_key(o) return? –  Gareth Mar 28 '12 at 12:49
2  
doesn't matter ;) I only intended to use it for an array with unique key-value-pairs. –  arik Mar 30 '12 at 20:31

9 Answers 9

up vote 53 down vote accepted

No standard method available. You need to iterate and you can create a simple helper:

Object.prototype.getKeyByValue = function( value ) {
    for( var prop in this ) {
        if( this.hasOwnProperty( prop ) ) {
             if( this[ prop ] === value )
                 return prop;
        }
    }
}

var test = {
   key1: 42,
   key2: 'foo'
};

test.getKeyByValue( 42 );  // returns 'key1'

One word of caution: Even if the above works, its generally a bad idea to extend any host or native object's .prototype. I did it here because it fits the issue very well. Anyway, you should probably use this function outside the .prototype and pass the object into it instead.

share|improve this answer
    
Ok, thanks! I hope they'll create a "native" function for that one day, though. –  arik Mar 28 '12 at 19:50
1  
Actually it's ok if you know things like that the for-in loop goes down the property chain which means "for(var key in obj)" would give you "getKeyByValue" as "key" at some point. –  prc322 Oct 22 '12 at 15:16
1  
@wubbewubbewubbe: its not copied, that is the beauty of prototypal inheritance. Think more like 'delegation' of it. However, I guess I did the warning very clearly, not because there is a problem of memory or performance, but you never know if you overwrite or shadow someone elses code. –  jAndy Mar 7 '13 at 11:34
1  
+1 for the word of caution alone. –  ChewOnThis_Trident Jul 3 '13 at 2:30
1  
Javascript is wonderful! :-) –  Wandile Nov 3 at 9:33

with Underscore.js

var hash = {
 foo: 1,
 bar: 2
};

(_.invert(hash))[1]; // => 'foo'
share|improve this answer
1  
Should be the accepted answer in my opinion. It astounds me how many people want to do monkey-patching instead. –  George Jempty Dec 24 '13 at 17:32
7  
@GeorgeJempty Not everyone wants to load a 5kb library for a simple key lookup ;) –  Doorknob Jan 12 at 2:45
2  
Don't be foolish, underscore.js does so much more, it makes a JS developer's life so much easier in so many ways –  George Jempty Jan 12 at 3:53
    
Just FYI for anyone looking for a solution that will get you ALL keys that match a value: this will not work. –  Brett Mar 20 at 6:45
1  
underscore keys will work too. underscorejs.org/#keys _.keys({one: 1, two: 2, three: 3}); => ["one", "two", "three"] –  Thaddeus Albers May 15 at 19:54

As said, iteration is needed. For instance, in modern browser you could have:

var key = Object.keys(obj).filter(function(key) {return obj[key] === value})[0];

Where value contains the value you're looking for. Said that, I would probably use a loop.

Otherwise you could use a proper "hashmap" object - there are several implementation in JS around - or implement by your own.

share|improve this answer
    
ES6: Object.keys(obj).or(o=>o[key] === value) –  Benjamin Gruenbaum Jun 23 '13 at 11:54
    
Unfortunately the arrow function is not any "modern" browser yet, so it's a bit useless at the moment – I'm using it in jetpack on Firefox Nightly, it will be in Firefox 22. Anyway, I'm not aware about any or array's method, and it's not clear to me its purpose here: I will appreciate some additional detail! :) –  ZER0 Jun 23 '13 at 18:40
    
As for arrow, it's coming and I'm waiting for it :) As for or sure! It was only recently evaluated and accepted (I don't think anyone implements it yet). What it does is find the first element of an array matching a predicate and return it. So [1,2,3,4].or(x=>x>2) would return 3 and [1,2,3,4,5].or(x=>x<3) would return 1. Something like C#'s FirstOrDefault :) –  Benjamin Gruenbaum Jun 23 '13 at 18:43
    
Yeah, arrow is coming but it will takes to be used widely – unless as I do, someone's working on a specific engine. I wasn't aware of new proposal for ES6, I thought was pretty closed: do you have a link about the or method? From what you mentioned it seems that it returns the item that match the predicate "or" the array itself? –  ZER0 Jun 24 '13 at 6:56
    
Looks like it was renamed to Array.prototype.find and Array.prototype.findIndex (for finding the index rather than the element :) github.com/Ralt/or/issues/1#issuecomment-14940411 –  Benjamin Gruenbaum Jun 24 '13 at 7:16

I use this function:

Object.prototype.getKey = function(value){
  for(var key in this){
    if(this[key] == value){
      return key;
    }
  }
  return null;
};

Usage:

// ISO 639: 2-letter codes
var languageCodes = {
  DA: 'Danish',
  DE: 'German',
  DZ: 'Bhutani',
  EL: 'Greek',
  EN: 'English',
  EO: 'Esperanto',
  ES: 'Spanish'
};

var key = languageCodes.getKey('Greek');
console.log(key); // EL
share|improve this answer
2  
+1 neat solution. But i have a question: Shouldn't you always check for obj.hasOwnProperty(key) or is it unnecessary in this case ? –  V-Light Jun 12 '13 at 9:38

I created the bimap library (https://github.com/alethes/bimap) which implements a powerful, flexible and efficient JavaScript bidirectional map interface. It has no dependencies and is usable both on the server-side (in Node.js, you can install it with npm install bimap) and in the browser (by linking to lib/bimap.js).

Basic operations are really simple:

var bimap = new BiMap;
bimap.push("k", "v");
bimap.key("k") // => "v"
bimap.val("v") // => "k"

bimap.push("UK", ["London", "Manchester"]);
bimap.key("UK"); // => ["London", "Manchester"]
bimap.val("London"); // => "UK"
bimap.val("Manchester"); // => "UK"

Retrieval of the key-value mapping is equally fast in both directions. There are no costly object/array traversals under the hood so the average access time remains constant regardless of the size of the data.

share|improve this answer
    
This saved me some time man, thanks! starred –  moobchunks Nov 2 at 22:48

Or, easier yet - create a new object with the keys and values in the order you want then do look up against that object. We have had conflicts using the prototype codes above. You don't have to use the String function around the key, that is optional.

 newLookUpObj = {};
 $.each(oldLookUpObj,function(key,value){
        newLookUpObj[value] = String(key);
    });
share|improve this answer

Since the values are unique, it should be possible to add the values as an additional set of keys. This could be done with the following shortcut.

var foo = {};
foo[foo.apple = "an apple"] = "apple";
foo[foo.pear = "a pear"] = "pear";

This would permit retrieval either via the key or the value:

var key = "apple";
var value = "an apple";

console.log(foo[value]); // "apple"
console.log(foo[key]); // "an apple"

This does assume that there are no common elements between the keys and values.

share|improve this answer

http://jsfiddle.net/rTazZ/2/

var a = new Array(); 
    a.push({"1": "apple", "2": "banana"}); 
    a.push({"3": "coconut", "4": "mango"});

    GetIndexByValue(a, "coconut");

    function GetIndexByValue(arrayName, value) {  
    var keyName = "";
    var index = -1;
    for (var i = 0; i < arrayName.length; i++) { 
       var obj = arrayName[i]; 
            for (var key in obj) {          
                if (obj[key] == value) { 
                    keyName = key; 
                    index = i;
                } 
            } 
        }
        //console.log(index); 
        return index;
    } 
share|improve this answer

This is a small extension to the Underscorejs method, and uses Lodash instead:

var getKeyByValue = function(searchValue) {
  return _.findKey(hash, function(hashValue) {
    return searchValue === hashValue;
  });
}

FindKey will search and return the first key which matches the value.
If you want the last match instead, use FindLastKey instead.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.