Come ottenere una chiave in un object JavaScript dal suo valore?

Ho un object JavaScript abbastanza semplice, che utilizzo come array associativo. C’è una semplice funzione che mi permette di ottenere la chiave per un valore, o devo iterare l’object e trovarlo manualmente?

con la libreria 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, nessun prototipo di mutazioni o librerie esterne.

Nessun metodo standard disponibile. Devi eseguire un’iterazione e puoi creare un semplice 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' 

Una parola di caucanvas : anche se quanto sopra funziona, è generalmente una ctriggers idea estendere qualsiasi .prototype un host o di un object nativo. L’ho fatto qui perché si adatta molto bene al problema. Ad ogni modo, dovresti probabilmente usare questa funzione al di fuori di .prototype e passare invece l’object in esso.

Come detto, è necessaria l’iterazione. Ad esempio, nel browser moderno potresti avere:

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

Dove value contiene il valore che stai cercando. Detto questo, probabilmente userei un ciclo.

Altrimenti potresti usare un object “hashmap” appropriato – ci sono diverse implementazioni in JS – o implementate da te.

AGGIORNAMENTO 2018

Sono passati sei anni, ma ho ancora un voto qui, quindi mi sento come una soluzione più moderna – per browser moderno / ambiente – dovrebbe essere menzionata nella risposta stessa e non solo nei commenti:

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

Ovviamente può essere anche una funzione:

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

Il modo di 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)]; } 

Creato per il compilatore di chiusura per estrarre il nome della chiave che sarà sconosciuto dopo la compilazione

Versione più sexy ma usando la funzione Object.entries futura

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

Io uso questa funzione:

 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 hai (o vuoi) una dipendenza su underscore.js, puoi usare la funzione findKey. Per esempio,

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

ES6

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

ES5

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

Mantieni il tuo prototipo pulito.

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

Esempio:

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

Soluzione non iterabile

Funzione principale:

 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 } 

Oggetto con chiavi e valori:

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

Test:

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

Ho creato la libreria bimap ( https://github.com/alethes/bimap ) che implementa un’interfaccia bidirezionale JavaScript potente, flessibile ed efficiente. Non ha dipendenze ed è utilizzabile sia sul lato server (in Node.js, è ansible installarlo con npm install bimap ) e nel browser (tramite collegamento a lib / bimap.js ).

Le operazioni di base sono davvero semplici:

 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" 

Il recupero della mapping dei valori chiave è altrettanto rapido in entrambe le direzioni. Non ci sono costosi attraversamenti di oggetti / array sotto il cofano, quindi il tempo di accesso medio rimane costante indipendentemente dalla dimensione dei dati.

Poiché i valori sono univoci, dovrebbe essere ansible aggiungere i valori come un set aggiuntivo di chiavi. Questo potrebbe essere fatto con la seguente scorciatoia.

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

Ciò consentirebbe il recupero tramite la chiave o il valore:

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

Ciò presuppone che non vi siano elementi comuni tra le chiavi e i valori.

O, ancora più facile – crea un nuovo object con le chiavi e i valori nell’ordine che vuoi, poi cerca contro quell’object. Abbiamo avuto conflitti usando i codici prototipo sopra. Non è necessario utilizzare la funzione String attorno alla chiave, che è opzionale.

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

Come se questa domanda non fosse stata battuta in poltiglia …

Eccone uno solo per la curiosità che ti porta …

Se sei sicuro che il tuo object avrà solo valori di stringa, potresti davvero esaurirti per evocare questa implementazione:

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

Forse c’è qualcosa di utile da build fuori da qui …

Spero che questo ti diverta.

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

Di solito raccomando lodash piuttosto che underscore.

Se ce l’hai, usalo.

Se non lo fai, dovresti prendere in considerazione l’utilizzo del pacchetto nash lodash.invert, che è piuttosto piccolo.

Ecco come puoi testarlo usando gulp:

1) Crea un file chiamato gulpfile.js con i seguenti contenuti:

 // 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) Installa il pacchetto lodash.invert e gulp

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

3) Verificare che funzioni:

 $ 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 

Riferimenti

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

https://lodash.com/

Differenze tra lodash e underscore

https://github.com/gulpjs/gulp

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

Per utilizzare il primo valore (ad es. output={"x":"a","y":"b"} ): output=Object.keys(input).reduceRight(function(accum,key,i){accum[input[key]]=key;return accum;},{})

Per usare l’ultimo valore (es. output={"x":"c","y":"b"} ): output=Object.keys(input).reduce(function(accum,key,i){accum[input[key]]=key;return accum;},{})

Per ottenere un array di chiavi per ogni valore (ad esempio 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;},{})

Questa è una piccola estensione del metodo Underscorejs e utilizza invece Lodash :

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

FindKey cercherà e restituirà la prima chiave che corrisponde al valore.
Se vuoi invece l’ultima partita, usa invece FindLastKey .

Ecco una soluzione di Lodash a questo che funziona per chiave piatta => object valore, piuttosto che un object nidificato. Il suggerimento della risposta accettata di utilizzare _.findKey funziona per oggetti con oggetti nidificati, ma non funziona in questa circostanza comune.

Questo approccio inverte l’object, scambiando le chiavi per i valori e quindi trova la chiave cercando il valore sul nuovo object (invertito). Se la chiave non viene trovata, viene restituito false , che preferisco undefined , ma puoi facilmente sostituirlo nel terzo parametro del metodo _.get in 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' ) + '"' ); 
  

Sottolineare la soluzione 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} 

Davvero semplice.

 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"