Como obter uma chave em um object JavaScript pelo seu valor?

Eu tenho um object JavaScript bastante simples, que eu uso como um array associativo. Existe uma function simples que me permite obter a chave para um valor, ou eu tenho que iterar o object e descobri-lo manualmente?

com a biblioteca Underscore.js :

 var hash = { foo: 1, bar: 2 }; (_.invert(hash))[1]; // => 'foo' 
 function getKeyByValue(object, value) { return Object.keys(object).find(key => object[key] === value); } 

ES6, sem mutações de protótipo ou bibliotecas externas.

Nenhum método padrão disponível. Você precisa iterar e criar um auxiliar simples:

 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' 

Uma palavra de caucanvas : Mesmo se o acima funcionar, é geralmente uma má ideia estender qualquer .prototype do object nativo ou do .prototype . Eu fiz isso aqui porque se encheckbox muito bem na questão. De qualquer forma, você provavelmente deveria usar essa function fora do .prototype e passar o object para ele.

Como dito, a iteração é necessária. Por exemplo, no navegador moderno, você poderia ter:

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

Onde value contém o valor que você está procurando. Disse que provavelmente usaria um loop.

Caso contrário, você pode usar um object “hashmap” adequado – há várias implementações no JS em volta – ou implementar por conta própria.

ATUALIZAÇÃO 2018

Seis anos se passaram, mas eu ainda recebo alguns votos aqui, então eu sinto que uma solução mais moderna – para navegador moderno / ambiente – deve ser mencionada na resposta em si e não apenas nos comentários:

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

Claro que também pode ser uma function:

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

A maneira lodash https://lodash.com/docs#findKey

 var users = { 'barney': { 'age': 36, 'active': true }, 'fred': { 'age': 40, 'active': false }, 'pebbles': { 'age': 1, 'active': true } }; _.findKey(users, { 'age': 1, 'active': true }); // → 'pebbles' 
 function extractKeyValue(obj, value) { return Object.keys(obj)[Object.values(obj).indexOf(value)]; } 

Feito para o compilador de encerramento para extrair o nome da chave que será desconhecido após a compilation

Versão mais sexy, mas usando a futura function Object.entries

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

Eu uso esta function:

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

Uso:

 // 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 

Se você tem (ou deseja) uma dependência em underscore.js, você pode usar a function findKey. Por exemplo,

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

es6

 _.findKey(test, (val) => val === 42); 

es5

 _.findKey(test, function(val) { return val === 42; }); 

Mantenha seu protótipo limpo.

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

Exemplo:

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

Solução não iterável

Função principal:

 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 } 

Objeto com chaves e valores:

 var greetings = { english : "hello", ukranian : "привіт" }; 

Teste:

 keyByValue("привіт"); // => "ukranian" 

Eu criei a biblioteca bimap ( https://github.com/alethes/bimap ) que implementa uma interface de mapa bidirecional JavaScript poderosa, flexível e eficiente. Ele não tem dependencies e é utilizável tanto no lado do servidor (no Node.js, você pode instalá-lo com o npm install bimap ) e no navegador (vinculando ao lib / bimap.js ).

Operações básicas são muito simples:

 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" 

A recuperação do mapeamento de valor-chave é igualmente rápida em ambas as direções. Não existem passagens dispendiosas de object / matriz sob o capô, portanto, o tempo médio de access permanece constante, independentemente do tamanho dos dados.

Como os valores são exclusivos, deve ser possível adicionar os valores como um conjunto adicional de chaves. Isso pode ser feito com o seguinte atalho.

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

Isso permitiria a recuperação por meio da chave ou do valor:

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

Isso pressupõe que não há elementos comuns entre as chaves e os valores.

Ou, ainda mais fácil – crie um novo object com as chaves e os valores na ordem desejada e, em seguida, procure esse object. Nós tivemos conflitos usando os códigos protótipos acima. Você não precisa usar a function String ao redor da chave, isso é opcional.

  newLookUpObj = {}; $.each(oldLookUpObj,function(key,value){ newLookUpObj[value] = String(key); }); 

Como se essa questão não tivesse sido vencida …

Aqui está um só por curiosidade que te traz …

Se você tem certeza de que seu object terá apenas valores de string, você pode realmente se exaurir para invocar esta implementação:

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

Talvez haja algo útil para construir daqui …

Espero que isso te divirta.

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

Eu normalmente recomendo lodash ao invés de sublinhar.

Se você tiver, use-o.

Se não o fizer, então você deve considerar o uso do pacote lodash.invert npm, que é bem pequeno.

Veja como você pode testá-lo usando gulp:

1) Crie um arquivo chamado gulpfile.js com o seguinte conteúdo:

 // 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) Instale o pacote lodash.invert e engula

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

3) Teste que funciona:

 $ 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 

Referências

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

https://lodash.com/

Diferenças entre lodash e sublinhado

https://github.com/gulpjs/gulp

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

Para usar o primeiro valor (por exemplo, output={"x":"a","y":"b"} ): output=Object.keys(input).reduceRight(function(accum,key,i){accum[input[key]]=key;return accum;},{})

Para usar o último valor (por exemplo, output={"x":"c","y":"b"} ): output=Object.keys(input).reduce(function(accum,key,i){accum[input[key]]=key;return accum;},{})

Para obter uma matriz de chaves para cada valor (por exemplo, output={"x":["c","a"],"y":["b"]} ): output=Object.keys(input).reduceRight(function(accum,key,i){accum[input[key]]=(accum[input[key]]||[]).concat(key);return accum;},{})

Esta é uma pequena extensão do método Underscorejs e usa o Lodash :

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

FindKey irá procurar e retornar a primeira chave que corresponde ao valor.
Se você quiser o último jogo, use FindLastKey .

Aqui está uma solução de Lodash para isso que funciona para flat key => value object, ao invés de um object nested. A sugestão da resposta aceita para usar _.findKey funciona para objects com objects nesteds, mas não funciona nesta circunstância comum.

Essa abordagem inverte o object, trocando chaves por valores e, em seguida, localiza a chave observando o valor no novo object (invertido). Se a chave não for encontrada, será retornado false , que prefiro undefined , mas você pode facilmente trocar isso no terceiro parâmetro do método _.get em _.get getKey() .

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

Solução de sublinhado js

 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} 

Realmente direto.

 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"