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

ari*_*rik 326 javascript object

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

小智 480

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

ES6,没有原型突变或外部库.

  • 辉煌!相当干净的方法-如果您的浏览器支持(我的方法是:)-Chrome 54) (6认同)
  • 好吧,如果你不支持IE11,真的很干净:-)如果是这样,你需要一个polyfill (6认同)
  • 哈哈。这并不慢,它是 O(n),这几乎是最好的运行时间。 (5认同)
  • 取决于实现,这可能需要* O(n)*空间,因为`keys()`实现了密钥集。 (4认同)
  • @BenWainwright:维护“BiMap”或等效项(Alethes 的答案)通常是解决更广泛问题的有效 O(1) 方法,但即使是一次性的,也至少可以使用“for in”进行迭代,并在找到一个时中断匹配,而不是提前创建整个键数组,从而导致最好的情况比最坏的情况更好。即,O(位置) 而不是 O(大小)。(本页上唯一比 O(size) 更糟糕的答案是愚蠢的 JSON 答案。) (3认同)
  • 干净但是很慢。 (2认同)
  • 如果多个键具有相同的值,请使用过滤器,而不要使用`function getKeyByValue(object,value){return Object.keys(object).filter(key => object [key] === value); }` (2认同)
  • @Ry-Alethes 的答案不是所问问题的有效答案...是的,如果您更改先决条件,当然您可以做很多事情,但提问者询问如何从普通对象中查找值。 (2认同)

jAn*_*ndy 173

没有可用的标准方法.您需要迭代,您可以创建一个简单的帮助器:

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'
Run Code Online (Sandbox Code Playgroud)

需要注意的一点是:即使上述工作正常,扩展任何主机或本机对象通常也是一个坏主意.prototype.我在这里做到了,因为它很适合这个问题.无论如何,你应该在这之外使用这个函数.prototype,并将对象传递给它.

  • 实际上如果你知道像for-in循环落在属性链上这意味着"for(var key in obj)"会在某些时候给你"getKeyByValue"作为"关键". (2认同)
  • @wubbewubbewubbe:它没有被复制,那就是原型继承的美.更像是"代表团".但是,我想我非常清楚地做了警告,不是因为存在内存或性能问题,而是你永远不知道你是否覆盖或影响了别人的代码. (2认同)
  • @jAndy 不是 ===,而是 ==。您的代码不适用于 ===。它返回未定义。 (2认同)

ZER*_*ER0 109

如上所述,需要迭代.例如,在现代浏览器中,您可以:

var key = Object.keys(obj).filter(function(key) {return obj[key] === value})[0];
Run Code Online (Sandbox Code Playgroud)

哪里value包含您正在寻找的价值.说,我可能会使用一个循环.

否则你可以使用一个合适的"hashmap"对象 - 在JS中有几个实现 - 或者由你自己实现.

更新2018年

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

const key = Object.keys(obj).find(key => obj[key] === value);
Run Code Online (Sandbox Code Playgroud)

当然它也可以是一个功能:

const getKeyByValue = (obj, value) => 
        Object.keys(obj).find(key => obj[key] === value);
Run Code Online (Sandbox Code Playgroud)

  • ES6:`Object.keys(obj).or(o => o [key] === value)` (17认同)
  • @sg552 正如后面提到的,`or` 被重命名。我相信现在你应该使用 [find](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find)。 (2认同)

ban*_*yan 98

Underscore.js图书馆:

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

(_.invert(hash))[1]; // => 'foo'
Run Code Online (Sandbox Code Playgroud)

  • @GeorgeJempty不是每个人都想加载一个5kb的库来进行简单的键查找;) (279认同)
  • "你可以用___库做___"从来都不是一个好的答案. (75认同)
  • 对于任何寻找能够获得所有匹配值的密钥的解决方案的人来说,仅供参考:这不起作用. (4认同)
  • 这不应该是公认的答案,它通过一个强制改变当前代码结构的库提出了一个解决方案 (3认同)
  • 下划线键也可以工作.http://underscorejs.org/#keys _.keys({one:1,two:2,three:3}); => ["一个","两个","三个"] (2认同)
  • 这不是一个好答案。这是一个外部库-__- (2认同)
  • OP清楚地询问`..是否有一个简单的函数...。`,所以这个答案真的出乎意料。 (2认同)
  • 这是一个不好的答案。 (2认同)

小智 40

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'
Run Code Online (Sandbox Code Playgroud)

  • 如果你的值很简单,比如字符串或整数,那么与期望相反,这将不起作用.例如`_.find_key({a:"A",b:"B"},"B"})`返回`undefined`,如所述[here](https://github.com/lodash/lodash/issues/528)你需要做`_.find_key({a:"A",b:"B"},_.partial(_.isEqual,"B")}) (7认同)
  • 仅供参考,"下划线方式":`_.findKey(用户,{'年龄':1,'有效':真}};`...它是一样的 (4认同)

Paw*_*wel 32

function extractKeyValue(obj, value) {
    return Object.keys(obj)[Object.values(obj).indexOf(value)];
}
Run Code Online (Sandbox Code Playgroud)

用于闭包编译器以提取编译后未知的密钥名称

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

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

  • 我认为这是2017+以来最好的,因为它使用纯JavaScript. (7认同)
  • 截至 2021 年,您获得了最快的解决方案。对于 15 个属性的对象,Object.values(...).find(...) 慢了 10%,我想知道对于大对象来说这会更好。 (2认同)

Ben*_*uer 21

我用这个函数:

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

用法:

// 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
Run Code Online (Sandbox Code Playgroud)

  • +1整洁的解决方案.但我有一个问题:你不应该总是检查`obj.hasOwnProperty(key)`还是在这种情况下不需要? (10认同)
  • 改变对象原型是不好的做法:/sf/ask/1666546381/ (3认同)

Kar*_*eem 16

保持原型清洁.

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

例:

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


Sys*_*ter 15

不可迭代的解决方案

主功能:

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
}
Run Code Online (Sandbox Code Playgroud)

具有键和值的对象:

var greetings = {
    english   : "hello",
    ukranian  : "??????"
};
Run Code Online (Sandbox Code Playgroud)

测试:

keyByValue("??????");
// => "ukranian"
Run Code Online (Sandbox Code Playgroud)

  • 更简单:`Object.keys(greetings)[Object.values(greetings).indexOf('привіт')]` (3认同)

cra*_*tin 14

如果你有(或想要)对underscore.js的依赖,你可以使用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'
Run Code Online (Sandbox Code Playgroud)

ES6

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'
Run Code Online (Sandbox Code Playgroud)

ES5

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'
Run Code Online (Sandbox Code Playgroud)


Sah*_*kar 14

这对我获取对象的键/值有用。

let obj = {
  'key1': 'value1',
  'key2': 'value2',
  'key3': 'value3',
  'key4': 'value4'
}

Object.keys(obj).map(function(k) {
  console.log("key with value: " + k + " = " + obj[k])
})
Run Code Online (Sandbox Code Playgroud)


Ale*_*hes 9

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

基本操作非常简单:

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"
Run Code Online (Sandbox Code Playgroud)

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


Den*_*rny 6

没有看到以下内容:

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)
Run Code Online (Sandbox Code Playgroud)
  
Run Code Online (Sandbox Code Playgroud)


Noe*_*ams 5

由于这些值是唯一的,因此应该可以将这些值添加为一组额外的键。这可以通过以下快捷方式完成。

var foo = {};
foo[foo.apple = "an apple"] = "apple";
foo[foo.pear = "a pear"] = "pear";
Run Code Online (Sandbox Code Playgroud)

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

var key = "apple";
var value = "an apple";

console.log(foo[value]); // "apple"
console.log(foo[key]); // "an apple"
Run Code Online (Sandbox Code Playgroud)

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


Fab*_*ini 5

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

  • 要使用第一个值(例如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)
Run Code Online (Sandbox Code Playgroud)

  • 要使用最后一个值(例如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)
Run Code Online (Sandbox Code Playgroud)

  • 要获取每个值的键数组(例如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)
Run Code Online (Sandbox Code Playgroud)


chi*_*ens 5

ES6 +一线

let key = Object.keys(obj).find(k=>obj[k]===value);
Run Code Online (Sandbox Code Playgroud)

要么

let key = Object.keys(obj)[Object.values(obj).indexOf(value)];
Run Code Online (Sandbox Code Playgroud)

要么

let key = ( Object.entries(obj).find(([k,v])=>v===value) || [] )[0];
Run Code Online (Sandbox Code Playgroud)