web-dev-qa-db-fra.com

Comment obtenir une clé dans un objet JavaScript par sa valeur?

J'ai un objet JavaScript assez simple, que j'utilise comme un tableau associatif. Existe-t-il une fonction simple permettant d’obtenir la clé d’une valeur ou dois-je itérer l’objet et le rechercher manuellement?

299
arik

avec Underscore.js bibliothèque:

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

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

ES6, pas de mutations prototypes ni de bibliothèques externes.

Exemple,

function getKeyByValue(object, value) {
  return Object.keys(object).find(key => object[key] === value);
}


const map = {"first" : "1", "second" : "2"};
console.log(getKeyByValue(map,"2"));
421
UncleLaz

Aucune méthode standard disponible. Vous devez itérer et vous pouvez créer un assistant simple:

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'

n mot d'avertissement: Même si cela fonctionne, c'est généralement une mauvaise idée d'étendre tout .prototype de l'hôte ou de l'objet natif. Je l'ai fait ici parce que cela cadre très bien avec le problème. Quoi qu'il en soit, vous devriez probablement utiliser cette fonction en dehors de .prototype et lui passer l'objet à la place.

171
jAndy

Comme dit, l'itération est nécessaire. Par exemple, dans un navigateur moderne, vous pourriez avoir:

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

value contient la valeur que vous recherchez. Cela dit, j'utiliserais probablement une boucle.

Sinon, vous pouvez utiliser un objet "hashmap" approprié - il y a plusieurs implémentations dans JS autour - ou implémenter vous-même.

MISE À JOUR 2018

Six ans ont passé, mais je reçois encore des votes ici, donc je me sens comme une solution plus moderne - pour les navigateurs/environnements modernes - devrait être mentionnée dans la réponse elle-même et pas seulement dans les commentaires:

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

Bien sûr cela peut être aussi une fonction:

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

La méthode 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'
40
cantbebothered
function extractKeyValue(obj, value) {
    return Object.keys(obj)[Object.values(obj).indexOf(value)];
}

Conçu pour le compilateur de fermeture pour extraire le nom de la clé qui sera inconnu après la compilation

Version plus sexy mais utilisant la future fonction Object.entries]

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

J'utilise cette fonction:

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

tilisation:

// 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
21
Benny Neugebauer

Gardez votre prototype propre.

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

Exemple:

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

Solution non-itérable

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

Objet avec clés et valeurs:

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

Tester:

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

Si vous travaillez avec Underscore ou Lodash , vous pouvez utiliser le _. findKey fonction:

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'
14
craigmichaelmartin

J'ai créé la bibliothèque bimap ( https://github.com/alethes/bimap ) qui implémente une puissante, flexible et interface de carte JavaScript bidirectionnelle efficace. Il n'a pas de dépendances et est utilisable à la fois côté serveur (dans Node.js, vous pouvez l'installer avec npm install bimap) et dans le navigateur (en vous connectant à lib/bimap .js ).

Les opérations de base sont vraiment 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"

La récupération du mappage clé-valeur est également rapide dans les deux sens. Il n'y a pas de traversées coûteuses d'objets/de tableaux sous le capot, le temps d'accès moyen reste donc constant quelle que soit la taille des données.

9
Alethes

Étant donné que les valeurs sont uniques, il devrait être possible de les ajouter en tant que jeu de clés supplémentaire. Cela pourrait être fait avec le raccourci suivant.

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

Cela permettrait la récupération via la clé ou la valeur:

var key = "Apple";
var value = "an Apple";

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

Cela suppose qu'il n'y a pas d'éléments communs entre les clés et les valeurs.

3
Noel Abrahams

Ou encore, encore plus facilement - créez un nouvel objet avec les clés et les valeurs dans l'ordre de votre choix, puis comparez-le avec cet objet. Nous avons eu des conflits en utilisant les codes prototypes ci-dessus. Vous n'êtes pas obligé d'utiliser la fonction Chaîne autour de la clé, c'est facultatif.

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

Comme si cette question n'avait pas été réduite à néant ...

En voici une juste pour la curiosité que cela vous amène ...

Si vous êtes certain que votre objet n'aura que des valeurs de chaîne, vous pouvez vraiment vous épuiser pour évoquer cette implémentation:

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

Peut-être qu'il y a quelque chose d'utile à construire à partir d'ici ...

J'espère que cela vous amuse.

2
Cody

Ceci est une petite extension de la méthode Underscorejs et utilise Lodash à la place:

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

FindKey volonté recherche et retourne la première clé qui correspond à la valeur.
Si vous voulez plutôt la dernière correspondance, utilisez FindLastKey .

1
kumarharsh

Voici une solution Lodash qui fonctionne pour une clé plate => objet de valeur, plutôt que pour un objet imbriqué. La suggestion de la réponse acceptée d'utiliser _.findKey fonctionne pour les objets avec des objets imbriqués, mais cela ne fonctionne pas dans cette situation courante.

Cette approche inverse l'objet en échangeant des clés pour des valeurs, puis recherche la clé en recherchant la valeur sur le nouvel objet (inversé). Si la clé n'est pas trouvée, alors false est renvoyé, ce que je préfère par rapport à undefined, mais vous pouvez facilement le remplacer dans le troisième paramètre de la méthode _.get de 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' ) + '"' );
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
1
Kevin Leary

Je recommande généralement lodash plutôt que le soulignement.

Si vous en avez, utilisez-le.

Si vous ne le faites pas, vous devriez envisager d'utiliser le paquetage lodash.invert npm, qui est plutôt petit.

Voici comment vous pouvez le tester en utilisant gulp:

1) Créez un fichier appelé gulpfile.js avec le contenu suivant:

// 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) Installez le package lodash.invert et gulp

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

3) Vérifiez que cela fonctionne:

$ 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

Références

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

https://lodash.com/

Différences entre lodash et underscore

https://github.com/gulpjs/gulp

1
l3x

Vraiment simple.

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"
1
onepix

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

Voici ma solution d'abord:

Par exemple, je suppose que nous avons un objet qui contient trois paires de valeurs:

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

Nous pouvons simplement écrire un findKey (tableau, valeur) qui prend deux paramètres qui sont un objet et la valeur de la clé que vous recherchez. En tant que telle, cette méthode est réutilisable et il n’est pas nécessaire d’itérer manuellement l’objet à chaque fois en ne transmettant que deux paramètres à cette fonction.

1
Ivan Zhang

Étant donné input={"a":"x", "b":"y", "c":"x"} ...

Pour utiliser la première valeur (par exemple output={"x":"a","y":"b"}): output=Object.keys(input).reduceRight(function(accum,key,i){accum[input[key]]=key;return accum;},{})

Pour utiliser la dernière valeur (par exemple output={"x":"c","y":"b"}): output=Object.keys(input).reduce(function(accum,key,i){accum[input[key]]=key;return accum;},{})

Pour obtenir un tableau de clés pour chaque valeur (par exemple 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;},{})

1
Fabio Beltramini

Souligner la solution 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}
0
Pooja