如何通过其值获取JavaScript对象中的键?

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

我有一个非常简单的javascript对象,我将它用作关联数组。是否有一个简单的函数允许我获取一个值的键,或者我必须迭代该对象并手动找到它?


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

无原型突变或外部库。

例子,

1
2
3
4
5
6
7
function getKeyByValue(object, value) {
  return Object.keys(object).find(key => object[key] === value);
}


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


没有可用的标准方法。您需要迭代,并且可以创建一个简单的助手:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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'

注意:即使上述方法有效,扩展任何主机或本机对象的.prototype通常也是一个坏主意。我在这里做是因为它很适合这个问题。无论如何,您可能应该在.prototype之外使用这个函数,并将对象传递给它。


使用Underscore.js库:

1
2
3
4
5
6
var hash = {
 foo: 1,
 bar: 2
};

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


如前所述,需要迭代。例如,在现代浏览器中,您可以有:

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

其中value包含您要查找的值。这么说,我可能会用一个循环。

否则,您可以使用一个适当的"hashmap"对象——在JS中有几个实现——或者由您自己实现。

更新2018

六年过去了,但我仍然在这里得到了一些投票,所以我觉得对于现代浏览器/环境来说,一个更现代的解决方案应该在答案中提到,而不仅仅是在评论中:

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

当然,它也可以是一个函数:

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


洛达什之路https://lodash.com/docs findkey

1
2
3
4
5
6
7
8
var users = {
  'barney':  { 'age': 36, 'active': true },
  'fred':    { 'age': 40, 'active': false },
  'pebbles': { 'age': 1,  'active': true }
};

_.findKey(users, { 'age': 1, 'active': true });
// → 'pebbles'


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

使闭包编译器提取编译后未知的密钥名

更性感的版本,但使用未来的Object.entries功能

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


我使用这个函数:

1
2
3
4
5
6
7
8
Object.prototype.getKey = function(value){
  for(var key in this){
    if(this[key] == value){
      return key;
    }
  }
  return null;
};

用途:

1
2
3
4
5
6
7
8
9
10
11
12
13
// 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


Keep your prototype clean.

1
2
3
4
5
6
7
8
function val2key(val,array){
    for (var key in array) {
        if(array[key] == val){
            return key;
        }
    }
 return false;
}

例子:

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

如果您使用的是下划线或lodash库,则可以使用.findkey函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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'


Non-iteratable solution

主要功能:

1
2
3
4
5
6
7
8
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
}

具有键和值的对象:

1
2
3
4
var greetings = {
    english   :"hello",
    ukranian  :"прив?т"
};

测试:

1
2
keyByValue("прив?т");
// =>"ukranian"

我创建了bimap库(https://github.com/alethes/bimap),它实现了一个强大、灵活和高效的javascript双向映射接口。它没有依赖关系,可以在服务器端(在node.js中,您可以使用npm install bimap安装它)和浏览器中(通过链接到lib/bimap.js)使用。

基本操作非常简单:

1
2
3
4
5
6
7
8
9
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"

检索关键值映射在两个方向上都同样快速。引擎盖下没有昂贵的对象/数组遍历,因此无论数据大小如何,平均访问时间都保持不变。


由于这些值是唯一的,所以应该可以将这些值作为一组附加键进行添加。这可以通过以下快捷方式完成。

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

这将允许通过键或值进行检索:

1
2
3
4
5
var key ="apple";
var value ="an apple";

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

这确实假定键和值之间没有公共元素。


或者,更简单——创建一个新的对象,按照您想要的顺序使用键和值,然后对照该对象进行查找。我们在使用上面的原型代码时遇到了冲突。您不必在键周围使用字符串函数,这是可选的。

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

好像这个问题还没有被打得一塌糊涂…

不管它带给你什么好奇心…

如果您确定您的对象将只有字符串值,那么您可能真的会耗尽自己的精力来调用这个实现:

1
2
3
4
5
6
7
8
9
10
11
12
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]);

也许这里有一些有用的东西…

希望这能让你开心。


http://jsfiddle.net/rtazz/2/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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;
    }


这是对underlinejs方法的一个小扩展,并使用lodash代替:

1
2
3
4
5
var getKeyByValue = function(searchValue) {
  return _.findKey(hash, function(hashValue) {
    return searchValue === hashValue;
  });
}

findkey将搜索并返回与值匹配的第一个键。如果需要最后一个匹配,请改用findlastkey。


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

使用第一个值(如output={"x":"a","y":"b"}):output=Object.keys(input).reduceRight(function(accum,key,i){accum[input[key]]=key;return accum;},{})

使用最后一个值(如output={"x":"c","y":"b"}output=Object.keys(input).reduce(function(accum,key,i){accum[input[key]]=key;return accum;},{})

要获得每个值的键数组(例如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
2
3
4
5
6
7
8
9
10
11
12
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

我们可以简单地编写一个findkey(数组,值),它接受两个参数,即一个对象和您要查找的键的值。因此,此方法是可重用的,您不需要每次通过仅为此函数传递两个参数来手动迭代对象。


这里有一个lodash解决方案,它适用于平面键=>值对象,而不是嵌套对象。接受的答案建议使用_.findKey适用于具有嵌套对象的对象,但在这种常见情况下不起作用。

此方法反转对象,交换值的键,然后通过查找新(反转)对象上的值来查找键。如果找不到密钥,则返回false,我比undefined更喜欢,但您可以在getKey()_.get方法的第三个参数中轻松地交换掉它。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
// 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' ) + '"' );
1
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js">


非常简单。

1
2
3
4
5
6
7
8
9
10
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"


我通常推荐罗达什而不是下划线。

如果你有,就用它。

如果不这样做,那么您应该考虑使用lodash.invert NPM包,它非常小。

以下是如何使用Gulp测试它:

1)创建一个名为gulpfile.js的文件,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
// 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)安装Lodash.Invert包和Gulp

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

3)测试其工作:

1
2
3
4
5
$ 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

工具书类

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

网址:https://lodash.com/

罗达什和下划线的区别

https://github.com/gulpjs/gulp


下划线JS解决方案

1
2
3
4
5
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}

保持简单!

您不需要通过复杂的方法或libs来过滤对象,javascript有一个内置的函数object.values。

例子:

1
2
3
4
5
6
7
8
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: {}

这将返回对象属性数据。

工具书类

https://developer.mozilla.org/pt-br/docs/web/javascript/reference/global_objects/object/values