简体   繁体   English

如何通过值获取 JavaScript object 中的键?

[英]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.我有一个非常简单的 JavaScript object,我将其用作关联数组。 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?是否有一个简单的 function 允许我获取值的键,或者我是否必须迭代 object 并手动找到它?

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

ES6, no prototype mutations or external libraries. ES6,没有原型突变或外部库。

Example,例子,

 function getKeyByValue(object, value) { return Object.keys(object).find(key => object[key] === value); } const map = {"first" : "1", "second" : "2"}; console.log(getKeyByValue(map,"2"));

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 .一个警告:即使上述方法有效,扩展任何主机或本机对象的.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.无论如何,您可能应该在.prototype之外使用此函数并将对象传递给它。

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.其中value包含您要查找的值。 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.否则你可以使用一个合适的“hashmap”对象——在 JS 中有几个实现——或者你自己实现。

UPDATE 2018 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);

With the Underscore.js library:使用Underscore.js库:

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

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

The lodash way https://lodash.com/docs#findKey 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'

ES6+ One Liners ES6+ 一个内胆

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);
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更性感的版本,但使用未来的Object.entries函数

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

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"

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

If you are working with Underscore or Lodash library, you can use the _.findKey function:如果您正在使用下划线Lodash库工作,你可以使用_.findKey功能:

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'

I created the bimap library ( https://github.com/alethes/bimap ) which implements a powerful, flexible and efficient JavaScript bidirectional map interface.我创建了bimap库 ( https://github.com/alethes/bimap ),它实现了一个强大、灵活和高效的 JavaScript 双向地图接口。 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 ).它没有依赖关系,并且在服务器端(在 Node.js 中,你可以使用npm install bimap安装它)和浏览器(通过链接到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.引擎盖下没有代价高昂的对象/数组遍历,因此无论数据大小如何,平均访问时间都保持不变。

didn't see the following:没有看到以下内容:

 const obj = { id: 1, name: 'Den' }; function getKeyByValue(obj, value) { return Object.entries(obj).find(([, name]) => value === name); } const [ key ] = getKeyByValue(obj, 'Den'); console.log(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.这确实假设键和值之间没有公共元素。

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

  • To use the first value (eg output={"x":"a","y":"b"} ):要使用第一个值(例如output={"x":"a","y":"b"} ):

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

  • To use the last value (eg output={"x":"c","y":"b"} ):要使用最后一个值(例如output={"x":"c","y":"b"} ):

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

  • To get an array of keys for each value (eg output={"x":["c","a"],"y":["b"]} ):要获取每个值的键数组(例如output={"x":["c","a"],"y":["b"]} ):

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

ES6方法:

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

this worked for me to get key/value of object.这对我有用以获取对象的键/值。

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

This is a small extension to the Underscorejs method, and uses Lodash instead:这是Underscorejs方法的一个小扩展,并使用Lodash代替:

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

FindKey will search and return the first key which matches the value. FindKey搜索并返回与该值匹配的第一个键
If you want the last match instead, use FindLastKey instead.如果您想要最后一个匹配项,请改用FindLastKey

Here's a Lodash solution to this that works for flat key => value object, rather than a nested object.这是一个 Lodash 解决方案,适用于平面键 => 值对象,而不是嵌套对象。 The accepted answer's suggestion to use _.findKey works for objects with nested objects, but it doesn't work in this common circumstance.接受的答案建议使用_.findKey适用于具有嵌套对象的对象,但在这种常见情况下不起作用。

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() .如果未找到密钥,则返回false ,我更喜欢undefined ,但您可以轻松地在getKey() _.get方法的第三个参数中将其替换掉。

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

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.我们可以简单地编写一个 findKey(array, value) ,它带有两个参数,它们是一个对象和您要查找的键的值。 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.因此,此方法是可重用的,您无需每次仅通过为此函数传递两个参数来手动迭代对象。

http://jsfiddle.net/rTazZ/2/ 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;
    } 

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.您不必在键周围使用 String 函数,这是可选的。

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

I typically recommend lodash rather than underscore.我通常推荐 lodash 而不是下划线。

If you have it, use it.如果你有它,请使用它。

If you don't, then you should consider using the lodash.invert npm package, which is pretty tiny.如果你不这样做,那么你应该考虑使用 lodash.invert npm 包,它非常小。

Here's how you can test it using gulp:以下是使用 gulp 测试它的方法:

1) Create a file called gulpfile.js with the following contents: 1) 创建一个名为 gulpfile.js 的文件,内容如下:

// 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 2) 安装 lodash.invert 包和 gulp

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

3) Test that it works: 3)测试它是否有效:

$ 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://www.npmjs.com/package/lodash.invert

https://lodash.com/ https://lodash.com/

Differences between lodash and underscore lodash 和下划线的区别

https://github.com/gulpjs/gulp https://github.com/gulpjs/gulp

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.希望这能让你开心。

Underscore js 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}

If you have an object with array values .如果您有一个带有数组值的对象。 Here is a good example.这是一个很好的例子。 Let us suppose you want to show an icon based on the extension of the file you have.让我们假设您想根据您拥有的文件的扩展名显示一个图标。 All the extensions with the same icon go under the same object value.具有相同图标的所有扩展都位于相同的对象值下。

Note: wrap the cases here in an object is better than do a switch with a lot of cases.注意:将这里的案例包装在一个对象中比在很多案例中进行切换要好。

Check the code snippet below (written in es6 ) to see how we return the specific key for the specific extension.检查下面的代码片段(用es6编写)以了解我们如何返回特定扩展的特定键。

I got the list of extensions from this git repo我从这个git repo 中得到了扩展列表

 // Oject that contains different icons for different extentions const icons = { "music": ["mp3", "m4a", "ogg", "acc", "flac","m3u", "wav"], "video": ["mp4","webm", "mkv", "avi", "mov", "m4v", "mpeg"], "image": ["jpg", "gif", "png", "jpeg", "tif", "psd", "raw", "ico"], "archives": ["zip", "rar", "tar", "dmg", "jar"], "3d-files": ["3ds", "dwg", "obj", "dae", "skp", "fbx"], "text": ["doc", "rtf", "txt", "odt", "tex"], "vector-graphics":["ai", "svg"], "pdf": ["pdf"], "data": ["xml", "csv", "xls"] } const get_icon_Key =( icons_object,file_extention) => { // For each key we chack if the value is contained in the list of values let key = Object.keys(icons_object).find( k=> icons[k].find( // At this leve we check if the extention exist in the array of the specific object value ie. 'music', 'video' ... icons_ext => icons_ext === file_extention) // if we find it means this is the key we are looking for ? true: false); return key } console.log(`The icon of for mp3 extention is: => ${get_icon_Key(icons,"mp3")}`) console.log(`The icon of for mp4 extention is: => ${get_icon_Key(icons,"mp4")}`)

Came here (in 2022) looking for a close variation of OP's question.来到这里(2022 年)寻找 OP 问题的近似变体。 Variation:变化:

How to find an object key based on a value, where keys may hold collections of values?如何根据值找到 object 键,其中键可能包含 collections 个值?

For this use case, switch from equality ( === ) to .includes() :对于这个用例,从相等 ( === ) 切换到.includes()

const foo = ['a', 'b','c'];
const bar = ['x', 'y', 'z'];
const bat = [2, 5, 'z'];
const obj = {foo: foo, bar: bar, bat: bat};

const findMe = (v) => {
  return Object.keys(obj).filter((k) => obj[k].includes(v))
}

findMe('y') // ['bar']
findMe('z') // ['bar', 'bat']

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 know I'm late but what do you think about this EMCMAScript 2017 solution I made today ?我知道我迟到了,但是您如何看待我今天制作的这个EMCMAScript 2017解决方案? It handles multiple matchs because what happens if two keys have the same values ?它处理多个匹配,因为如果两个键具有相同的值会发生什么? This is why I created this little snippet.这就是我创建这个小片段的原因。

When there's one match, it returns just a string but when there are several matchs, it returns an array.当有一个匹配项时,它只返回一个字符串,但当有多个匹配项时,它返回一个数组。

 let object = { nine_eleven_was_a_inside_job: false, javascript_isnt_useful: false } // Complex, dirty but useful. Handle mutiple matchs which is the main difficulty. Object.prototype.getKeyByValue = function (val) { let array = []; let array2 = []; // Get all the key in the object. for(const [key] of Object.entries(this)) { if (this[key] == val) { // Putting them in the 1st array. array.push(key) } } // List all the value of the 1st array. for(key of array) { // "If one of the key in the array is equal to the value passed in the function (val), it means that 'val' correspond to it." if(this[key] == val) { // Push all the matchs. array2.push(key); } } // Check the lenght of the array. if (array2.length < 2) { // If it's under 2, only return the single value but not in the array. return array2[0]; } else { // If it's above or equal to 2, return the entire array. return array2; } } /* Basic way to do it wich doesn't handle multiple matchs. let getKeyByValue = function (object, val) { for(const [key, content] of Object.entries(object)) { if (object[key] === val) { return key } } } */ console.log(object.getKeyByValue(false))

We can use simple function to get the value passed key something below我们可以使用简单的 function 来获取下面传递的值

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

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 .您不需要通过复杂的方法或库过滤对象,Javascript 有一个名为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 https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Object/values

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM