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

720

我有一个非常简单的JavaScript对象,我将其用作关联数组。是否有一个简单的函数可以让我获取值对应的键名,还是我必须手动迭代对象并找到它?


没有这样的标准函数可以实现这个功能。如果映射是真正的双向的,那么构建一个“翻转”的映射并对其进行索引就很容易了。否则,一个简单的属性迭代器(可能带有hasOwnProperty保护)和一个隐藏在函数内部的早期返回就可以很好地解决问题... - user166390
如果一个对象被多个键引用,这该怎么办呢? var o = []; var map = {first: o, second: o}find_key(o) 会返回什么? - Gareth
5
没问题 ;) 我只是打算将它用于具有唯一键值对的数组。 - arik
可能是获取JavaScript键/值对象键的最佳方法的重复问题。 - Andy
1
我已经制作了一个没有迭代的版本 https://dev59.com/kmkw5IYBdhLWcg3waZ74#36705765。测试所有建议的解决方案在jsfiddle上将是有趣的。 - Pawel
31个回答

2

我来到这里(2022年)寻找OP问题的一个类似变体。 变体如下:

如何基于值查找对象键,其中键可能包含值的集合?

对于这种用例,请从相等性(===)切换到.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']

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

@Fr0zenFyr:以下链接可以更好地回答你的问题 - https://dev59.com/kmoy5IYBdhLWcg3wo_cn - Atur

2

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

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

1

我通常推荐使用lodash而不是underscore。

如果您有它,请使用它。

如果您没有,那么您应该考虑使用lodash.invert npm包,它非常小。

以下是使用gulp进行测试的方法:

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

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

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

参考资料

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

https://lodash.com/

Lodash和Underscore的区别

https://github.com/gulpjs/gulp


为什么要涉及Gulp?只需运行脚本即可... - Ry-

1

仿佛这个问题还没有被研究透彻...

以下内容仅供好奇心的满足...

如果您确定您的对象只包含字符串值,您可以尝试使用以下实现:

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

也许这里有一些有用的东西可以借鉴...希望这能逗乐你。

1
如果您有一个包含数组值的对象。这是一个很好的例子。假设您想根据文件扩展名显示图标。所有具有相同图标的扩展名都属于同一个对象值。

注意:将这里的情况包装在对象中比使用许多情况的开关更好。

检查下面的代码片段(用es6编写)以查看如何返回特定扩展名的特定键。
我从这个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")}`)


如果你已经将icons_object作为参数传递进来了,为什么还要在函数中引用外部的icons对象呢? - David Axelrod

1

Underscore 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

我知道我来晚了,但你觉得我今天做的这个EMCMAScript 2017解决方案怎么样?它可以处理多个匹配,因为如果两个键具有相同的值会发生什么?这就是我创建这个小片段的原因。

当只有一个匹配时,它返回一个字符串,但当有多个匹配时,它返回一个数组。

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


0
我们可以使用简单的函数来获取传递键下面的值。
const getKeyByValue = (object, value) => Object.keys(object).find(key => object[key] === value)

0

非常简单。

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"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接