[javascript] How to get a key in a JavaScript object by its value?

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 a value, or do I have to iterate the object and find it out manually?

This question is related to javascript object

The answer is


As if this question hasn't been beaten to a pulp...

Here's one just for whatever curiosity it brings you...

If you're sure that your object will have only string values, you could really exhaust yourself to conjure up this implementation:

var o = { a: '_A', b: '_B', c: '_C' }
  , json = JSON.stringify(o)
  , split = json.split('')
  , nosj = split.reverse()
  , o2 = nosj.join('');

var reversed = o2.replace(/[{}]+/g, function ($1) { return ({ '{':'}', '}':'{' })[$1]; })
  , object = JSON.parse(reversed)
  , value = '_B'
  , eulav = value.split('').reverse().join('');

console.log('>>', object[eulav]);

Maybe there's something useful to build off of here...

Hope this amuses you.


ES6 methods:

Object.fromEntries(Object.entries(a).map(b => b.reverse()))['value_you_look_for']

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

this worked for me to get key/value of object.

_x000D_
_x000D_
let obj = {_x000D_
        'key1': 'value1',_x000D_
        'key2': 'value2',_x000D_
        'key3': 'value3',_x000D_
        'key4': 'value4'_x000D_
    }_x000D_
    Object.keys(obj).map(function(k){ _x000D_
    console.log("key with value: "+k +" = "+obj[k])    _x000D_
    _x000D_
    })_x000D_
    
_x000D_
_x000D_
_x000D_


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.


The lodash way https://lodash.com/docs#findKey

_x000D_
_x000D_
var users = {_x000D_
  'barney':  { 'age': 36, 'active': true },_x000D_
  'fred':    { 'age': 40, 'active': false },_x000D_
  'pebbles': { 'age': 1,  'active': true }_x000D_
};_x000D_
_x000D_
_.findKey(users, { 'age': 1, 'active': true });_x000D_
// ? 'pebbles'
_x000D_
_x000D_
_x000D_


If you are working with Underscore or Lodash library, you can use the _.findKey function:

var users = {
  'barney':  { 'age': 36, 'active': true },
  'fred':    { 'age': 40, 'active': false },
  'pebbles': { 'age': 1,  'active': true }
};

_.findKey(users, function(o) { return o.age < 40; });
// => 'barney' (iteration order is not guaranteed)

// The `_.matches` iteratee shorthand.
_.findKey(users, { 'age': 1, 'active': true });
// => 'pebbles'

// The `_.matchesProperty` iteratee shorthand.
_.findKey(users, ['active', false]);
// => 'fred'

// The `_.property` iteratee shorthand.
_.findKey(users, 'active');
// => 'barney'

Really straightforward.

const CryptoEnum = Object.freeze({
                    "Bitcoin": 0, "Ethereum": 1, 
                    "Filecoin": 2, "Monero": 3, 
                    "EOS": 4, "Cardano": 5, 
                    "NEO": 6, "Dash": 7, 
                    "Zcash": 8, "Decred": 9 
                  });

Object.entries(CryptoEnum)[0][0]
// output => "Bitcoin"

I typically recommend lodash rather than underscore.

If you have it, use it.

If you don't, then you should consider using the lodash.invert npm package, which is pretty tiny.

Here's how you can test it using gulp:

1) Create a file called gulpfile.js with the following contents:

// Filename: gulpfile.js
var gulp = require('gulp');
var invert = require('lodash.invert');   
gulp.task('test-invert', function () {
  var hash = {
    foo: 1,
    bar: 2
  };
  var val = 1;
  var key = (invert(hash))[val];  // << Here's where we call invert!
  console.log('key for val(' + val + '):', key);
});

2) Install the lodash.invert package and gulp

$ npm i --save lodash.invert && npm install gulp

3) Test that it works:

$ gulp test-invert
[17:17:23] Using gulpfile ~/dev/npm/lodash-invert/gulpfile.js
[17:17:23] Starting 'test-invert'...
key for val(1): foo
[17:17:23] Finished 'test-invert' after 511 µs

References

https://www.npmjs.com/package/lodash.invert

https://lodash.com/

Differences between lodash and underscore

https://github.com/gulpjs/gulp


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.


Underscore js solution

let samplLst = [{id:1,title:Lorem},{id:2,title:Ipsum}]
let sampleKey = _.findLastIndex(samplLst,{_id:2});
//result would be 1
console.log(samplLst[sampleKey])
//output - {id:2,title:Ipsum}

With the Underscore.js library:

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

(_.invert(hash))[1]; // => 'foo'

Given input={"a":"x", "b":"y", "c":"x"} ...

  • To use the first value (e.g. output={"x":"a","y":"b"}):

_x000D_
_x000D_
input = {_x000D_
  "a": "x",_x000D_
  "b": "y",_x000D_
  "c": "x"_x000D_
}_x000D_
output = Object.keys(input).reduceRight(function(accum, key, i) {_x000D_
  accum[input[key]] = key;_x000D_
  return accum;_x000D_
}, {})_x000D_
console.log(output)
_x000D_
_x000D_
_x000D_

  • To use the last value (e.g. output={"x":"c","y":"b"}):

_x000D_
_x000D_
input = {_x000D_
  "a": "x",_x000D_
  "b": "y",_x000D_
  "c": "x"_x000D_
}_x000D_
output = Object.keys(input).reduce(function(accum, key, i) {_x000D_
  accum[input[key]] = key;_x000D_
  return accum;_x000D_
}, {})_x000D_
console.log(output)
_x000D_
_x000D_
_x000D_

  • To get an array of keys for each value (e.g. output={"x":["c","a"],"y":["b"]}):

_x000D_
_x000D_
input = {_x000D_
  "a": "x",_x000D_
  "b": "y",_x000D_
  "c": "x"_x000D_
}_x000D_
output = Object.keys(input).reduceRight(function(accum, key, i) {_x000D_
  accum[input[key]] = (accum[input[key]] || []).concat(key);_x000D_
  return accum;_x000D_
}, {})_x000D_
console.log(output)
_x000D_
_x000D_
_x000D_


Keep it simple!

You don't need to filter the object through sophisticated methods or libs, Javascript has a built in function called Object.values.

Example:

let myObj = {jhon: {age: 20, job: 'Developer'}, marie: {age: 20, job: 
'Developer'}};

function giveMeTheObjectData(object, property) {
   return Object.values(object[property]);
}

giveMeTheObjectData(myObj, 'marie'); // => returns marie: {}

This will return the object property data.

References

https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Object/values


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.


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.

UPDATE 2018

Six years passed, but I still get some vote here, so I feel like a more modern solution – for modern browser/environment – should be mentioned in the answer itself and not just in the comments:

const key = Object.keys(obj).find(key => obj[key] === value);

Of course it can be also a function:

const getKeyByValue = (obj, value) => 
        Object.keys(obj).find(key => obj[key] === value);

Here is my solution first:

For example, I suppose that we have an object that contains three value pairs:

function findKey(object, value) {

    for (let key in object)
        if (object[key] === value) return key;

    return "key is not found";
}

const object = { id_1: "apple", id_2: "pear", id_3: "peach" };

console.log(findKey(object, "pear"));
//expected output: id_2

We can simply write a findKey(array, value) that takes two parameters which are an object and the value of the key you are looking for. As such, this method is reusable and you do not need to manually iterate the object every time by only passing two parameters for this function.


didn't see the following:

_x000D_
_x000D_
const obj = {_x000D_
  id: 1,_x000D_
  name: 'Den'_x000D_
};_x000D_
_x000D_
function getKeyByValue(obj, value) {_x000D_
  return Object.entries(obj).find(([, name]) => value === name);_x000D_
}_x000D_
_x000D_
const [ key ] = getKeyByValue(obj, 'Den');_x000D_
console.log(key)
_x000D_
  
_x000D_
_x000D_
_x000D_


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

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.


Here's a Lodash solution to this that works for flat key => value object, rather than a nested object. The accepted answer's suggestion to use _.findKey works for objects with nested objects, but it doesn't work in this common circumstance.

This approach inverts the object, swapping keys for values, and then finds the key by looking up the value on the new (inverted) object. If the key isn't found then false is returned, which I prefer over undefined, but you could easily swap this out in the third parameter of the _.get method in getKey().

_x000D_
_x000D_
// Get an object's key by value_x000D_
var getKey = function( obj, value ) {_x000D_
 var inverse = _.invert( obj );_x000D_
 return _.get( inverse, value, false );_x000D_
};_x000D_
_x000D_
// US states used as an example_x000D_
var states = {_x000D_
 "AL": "Alabama",_x000D_
 "AK": "Alaska",_x000D_
 "AS": "American Samoa",_x000D_
 "AZ": "Arizona",_x000D_
 "AR": "Arkansas",_x000D_
 "CA": "California",_x000D_
 "CO": "Colorado",_x000D_
 "CT": "Connecticut",_x000D_
 "DE": "Delaware",_x000D_
 "DC": "District Of Columbia",_x000D_
 "FM": "Federated States Of Micronesia",_x000D_
 "FL": "Florida",_x000D_
 "GA": "Georgia",_x000D_
 "GU": "Guam",_x000D_
 "HI": "Hawaii",_x000D_
 "ID": "Idaho",_x000D_
 "IL": "Illinois",_x000D_
 "IN": "Indiana",_x000D_
 "IA": "Iowa",_x000D_
 "KS": "Kansas",_x000D_
 "KY": "Kentucky",_x000D_
 "LA": "Louisiana",_x000D_
 "ME": "Maine",_x000D_
 "MH": "Marshall Islands",_x000D_
 "MD": "Maryland",_x000D_
 "MA": "Massachusetts",_x000D_
 "MI": "Michigan",_x000D_
 "MN": "Minnesota",_x000D_
 "MS": "Mississippi",_x000D_
 "MO": "Missouri",_x000D_
 "MT": "Montana",_x000D_
 "NE": "Nebraska",_x000D_
 "NV": "Nevada",_x000D_
 "NH": "New Hampshire",_x000D_
 "NJ": "New Jersey",_x000D_
 "NM": "New Mexico",_x000D_
 "NY": "New York",_x000D_
 "NC": "North Carolina",_x000D_
 "ND": "North Dakota",_x000D_
 "MP": "Northern Mariana Islands",_x000D_
 "OH": "Ohio",_x000D_
 "OK": "Oklahoma",_x000D_
 "OR": "Oregon",_x000D_
 "PW": "Palau",_x000D_
 "PA": "Pennsylvania",_x000D_
 "PR": "Puerto Rico",_x000D_
 "RI": "Rhode Island",_x000D_
 "SC": "South Carolina",_x000D_
 "SD": "South Dakota",_x000D_
 "TN": "Tennessee",_x000D_
 "TX": "Texas",_x000D_
 "UT": "Utah",_x000D_
 "VT": "Vermont",_x000D_
 "VI": "Virgin Islands",_x000D_
 "VA": "Virginia",_x000D_
 "WA": "Washington",_x000D_
 "WV": "West Virginia",_x000D_
 "WI": "Wisconsin",_x000D_
 "WY": "Wyoming"_x000D_
};_x000D_
_x000D_
console.log( 'The key for "Massachusetts" is "' + getKey( states, 'Massachusetts' ) + '"' );
_x000D_
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
_x000D_
_x000D_
_x000D_


Keep your prototype clean.

function val2key(val,array){
    for (var key in array) {
        if(array[key] == val){
            return key;
        }
    }
 return false;
}

Example:

var map = {"first" : 1, "second" : 2};
var key = val2key(2,map); /*returns "second"*/

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

Non-iteratable solution

Main function:

var keyByValue = function(value) {

    var kArray = Object.keys(greetings);        // Creating array of keys
    var vArray = Object.values(greetings);      // Creating array of values
    var vIndex = vArray.indexOf(value);         // Finding value index 

    return kArray[vIndex];                      // Returning key by value index
}

Object with keys and values:

var greetings = {
    english   : "hello",
    ukranian  : "??????"
};

Test:

keyByValue("??????");
// => "ukranian"

function extractKeyValue(obj, value) {
    return Object.keys(obj)[Object.values(obj).indexOf(value)];
}

Made for closure compiler to extract key name which will be unknown after compilation

More sexy version but using future Object.entries function

function objectKeyByValue (obj, val) {
  return Object.entries(obj).find(i => i[1] === val);
}

ES6+ One Liners

let key = Object.keys(obj).find(k=>obj[k]===value);

Return all keys with the value:

let keys = Object.keys(obj).filter(k=>obj[k]===value);