我有一个非常简单的 JavaScript 对象,我将其用作关联数组。是否有一个简单的函数允许我获取值的键,或者我必须迭代对象并手动找到它?
var o = []; var map = {first: o, second: o}
。 find_key(o)
会返回什么?
function getKeyByValue(object, value) {
return Object.keys(object).find(key => object[key] === value);
}
ES6,没有原型突变或外部库。
例子,
function getKeyByValue(object, value) { return Object.keys(object).find(key => object[key] === value); } 常量映射 = {“第一”:“1”,“第二”:“2”}; console.log(getKeyByValue(map,"2"));
没有可用的标准方法。你需要迭代,你可以创建一个简单的助手:
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
之外使用此函数并将对象传递给它。
.toString()
像 obj[ key ].toString()
并在需要时添加到值...
如前所述,需要迭代。例如,在现代浏览器中,您可以:
var key = Object.keys(obj).filter(function(key) {return obj[key] === value})[0];
其中 value
包含您要查找的值。说,我可能会使用循环。
否则,您可以使用适当的“hashmap”对象——在 JS 中有几个实现——或者你自己实现。
2018 年更新
六年过去了,但我仍然在这里获得了一些投票,所以我觉得一个更现代的解决方案 - 对于现代浏览器/环境 - 应该在答案本身中提及,而不仅仅是在评论中:
const key = Object.keys(obj).find(key => obj[key] === value);
当然它也可以是一个函数:
const getKeyByValue = (obj, value) =>
Object.keys(obj).find(key => obj[key] === value);
Object.keys(obj).or(o=>o[key] === value)
or
,当然!它最近才被评估和接受(我认为还没有人实现它)。它所做的是找到与谓词匹配的数组的第一个元素并将其返回。因此 [1,2,3,4].or(x=>x>2)
将返回 3
而 [1,2,3,4,5].or(x=>x<3)
将返回 1
。类似于 C# 的 FirstOrDefault :)
or
方法的链接吗?从您提到的内容来看,它似乎返回与谓词“或”数组本身匹配的项目?
or
被重命名。我相信现在您应该使用 find。
使用 Underscore.js 库:
var hash = {
foo: 1,
bar: 2
};
(_.invert(hash))[1]; // => 'foo'
_.chain(hash).pairs().findWhere({1: 1}).value()[0]
ES6+ 一号线
let key = Object.keys(obj).find(k=>obj[k]===value);
返回具有值的所有键:
let keys = Object.keys(obj).filter(k=>obj[k]===value);
如果值为 Array
或 Object
:
let keys = Object.keys(obj).filter(k=>JSON.stringify(obj[k])===JSON.stringify(value));
lodash 方式 https://lodash.com/docs#findKey
var users = { 'barney': { 'age': 36, 'active': true }, 'fred': { 'age': 40, 'active': false }, 'pebbles': { 'age': 1 , '活跃': 真 } }; _.findKey(users, {'age': 1, 'active': true }); // → '鹅卵石'
_.findKey(users, { 'age': 1, 'active': true });
...它是一样的
_.find_key({a: "A", b:"B"}, "B"})
返回undefined
,如前所述 here 您需要执行 _.find_key({a: "A", b:"B"}, _.partial(_.isEqual,"B")})
_.invert(haystack)[needle]
_.findKey({a: "A", b: "B"}, value => value === "B") // => "b"
,因为第二个参数是谓词。简写 _.findKey({...}, "B")
将查找名为 B
的属性:{b: { B: ... } }
function extractKeyValue(obj, value) {
return Object.keys(obj)[Object.values(obj).indexOf(value)];
}
用于闭包编译器提取编译后未知的键名
更性感的版本,但使用未来的 Object.entries
功能
function objectKeyByValue (obj, val) {
return Object.entries(obj).find(i => i[1] === val);
}
Object.entries(obj).find(i => i[1] === val);
使用 filter
而不是 Object.entries(obj).filter(i => i[1] === val);
Object.entries(obj).find( ([ key, value ]) => value === val);
我使用这个功能:
Object.prototype.getKey = function(value){
for(var key in this){
if(this[key] == value){
return key;
}
}
return null;
};
用法:
// 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
obj.hasOwnProperty(key)
还是在这种情况下没有必要?
不可迭代的解决方案
主功能:
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
}
带有键和值的对象:
var greetings = {
english : "hello",
ukranian : "привіт"
};
测试:
keyByValue("привіт");
// => "ukranian"
Object.keys(greetings )[Object.values(greetings ).indexOf('привіт')]
保持原型清洁。
function val2key(val,array){
for (var key in array) {
if(array[key] == val){
return key;
}
}
return false;
}
例子:
var map = {"first" : 1, "second" : 2};
var key = val2key(2,map); /*returns "second"*/
如果您使用 Underscore 或 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'
我创建了 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"
键值映射的检索在两个方向上都同样快。引擎盖下没有代价高昂的对象/数组遍历,因此无论数据大小如何,平均访问时间都保持不变。
这对我来说可以获取对象的键/值。
让 obj = { 'key1': 'value1', 'key2': 'value2', 'key3': 'value3', 'key4': 'value4' } Object.keys(obj).map(function(k){ console.log("键值:"+k +" = "+obj[k]) })
没有看到以下内容:
const obj = { id: 1, name: 'Den' }; function getKeyByValue(obj, value) { return Object.entries(obj).find(([, name]) => value === name); } const [ key ] = getKeyByValue(obj, 'Den');控制台日志(键)
由于这些值是唯一的,因此应该可以将这些值添加为一组额外的键。这可以通过以下快捷方式完成。
var foo = {};
foo[foo.apple = "an apple"] = "apple";
foo[foo.pear = "a pear"] = "pear";
这将允许通过键或值进行检索:
var key = "apple";
var value = "an apple";
console.log(foo[value]); // "apple"
console.log(foo[key]); // "an apple"
这确实假设键和值之间没有共同的元素。
给定 input={"a":"x", "b":"y", "c":"x"}
...
要使用第一个值(例如 output={"x":"a","y":"b"}):
输入 = { "a": "x", "b": "y", "c": "x" } 输出 = Object.keys(input).reduceRight(function(accum, key, i) { accum[input [key]] = key; return accum; }, {}) console.log(output)
要使用最后一个值(例如 output={"x":"c","y":"b"}):
输入 = { "a": "x", "b": "y", "c": "x" } 输出 = Object.keys(input).reduce(function(accum, key, i) { accum[input [key]] = key; return accum; }, {}) console.log(output)
获取每个值的键数组(例如 output={"x":["c","a"],"y":["b"]}):
输入 = { "a": "x", "b": "y", "c": "x" } 输出 = Object.keys(input).reduceRight(function(accum, key, i) { accum[input [key]] = (accum[input[key]] || []).concat(key); return accum; }, {}) console.log(output)
这是对 Underscorejs 方法的一个小扩展,而是使用 Lodash:
var getKeyByValue = function(searchValue) {
return _.findKey(hash, function(hashValue) {
return searchValue === hashValue;
});
}
FindKey 将 search and return the first key 匹配该值。
如果您想要最后一个匹配,请改用 FindLastKey。
ES6 方法:
Object.fromEntries(Object.entries(a).map(b => b.reverse()))['value_you_look_for']
这是一个适用于平键的 Lodash 解决方案 =>值对象,而不是嵌套对象。接受答案的使用 _.findKey
的建议适用于具有嵌套对象的对象,但在这种常见情况下不起作用。
这种方法反转对象,用键交换值,然后通过在新(反转)对象上查找值来找到键。如果未找到密钥,则返回 false
,我更喜欢 undefined
,但您可以在 getKey()
的 _.get
方法的第三个参数中轻松地将其换出。
// 通过值获取对象的键 var getKey = function( obj, value ) { var inverse = _.invert( obj );返回_.get(逆,值,假); }; // 以美国各州为例 var states = { "AL": "Alabama", "AK": "Alaska", "AS": "American Samoa", "AZ": "Arizona", "AR": "阿肯色州”,“CA”:“加利福尼亚”,“CO”:“科罗拉多”,“CT”:“康涅狄格”,“DE”:“特拉华”,“DC”:“哥伦比亚特区”,“FM”:“密克罗尼西亚联邦”,“FL”:“佛罗里达”,“GA”:“乔治亚”,“GU”:“关岛”,“HI”:“夏威夷”,“ID”:“爱达荷”,“IL”: “伊利诺伊州”、“IN”:“印第安纳州”、“IA”:“爱荷华州”、“KS”:“堪萨斯州”、“KY”:“肯塔基州”、“LA”:“路易斯安那州”、“ME”:“缅因州” ”,“MH”:“马绍尔群岛”,“MD”:“马里兰”,“MA”:“马萨诸塞”,“MI”:“密歇根”,“MN”:“明尼苏达”,“MS”:“密西西比” ,“MO”:“密苏里”,“MT”:“蒙大拿”,“NE”:“内布拉斯加州”,“NV”:“内华达”,“NH”:“新罕布什尔”,“NJ”:“新泽西” ,“NM”:“新墨西哥”,“NY”:“纽约”,“NC”:“北卡罗来纳”,“ND”:“北达科他州”,“MP”:“北马里亚纳群岛”,“OH” :“俄亥俄”、“OK”:“俄克拉荷马”、“OR”:“俄勒冈”、“PW”:“帕劳”、“PA”:“宾夕法尼亚”、“PR”:“波多黎各”、“RI”: “罗德岛”、“SC”:“南卡罗来纳”、“SD”:“南” h Dakota”,“TN”:“Tennessee”,“TX”:“Texas”,“UT”:“Utah”,“VT”:“Vermont”,“VI”:“Virgin Islands”,“VA”:“弗吉尼亚”,“WA”:“华盛顿”,“WV”:“西弗吉尼亚”,“WI”:“威斯康星”,“WY”:“怀俄明”}; console.log( '“马萨诸塞州”的关键字是 "' + getKey( states, 'Massachusetts' ) + '"' );
这是我的解决方案:
例如,我假设我们有一个包含三个值对的对象:
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(array, value) ,它接受两个参数,一个对象和您要查找的键的值。因此,此方法是可重用的,您无需每次都手动迭代对象,只需为此函数传递两个参数。
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;
}
或者,更简单 - 按照您想要的顺序使用键和值创建一个新对象,然后查找该对象。我们在使用上面的原型代码时遇到了冲突。您不必在键周围使用 String 函数,这是可选的。
newLookUpObj = {};
$.each(oldLookUpObj,function(key,value){
newLookUpObj[value] = String(key);
});
我通常推荐 lodash 而不是下划线。
如果你有它,使用它。
如果你不这样做,那么你应该考虑使用非常小的 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
Differences between lodash and underscore
https://github.com/gulpjs/gulp
好像这个问题还没有被打到纸浆...
这里有一个只是为了它给你带来的任何好奇心......
如果您确定您的对象将只有字符串值,那么您真的可以用尽自己的力量来想出这个实现:
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]);
也许这里有一些有用的东西可以建立......
希望这能逗你开心。
下划线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}
如果您有一个具有数组值的对象。这是一个很好的例子。让我们假设您想根据您拥有的文件的扩展名显示一个图标。具有相同图标的所有扩展都在相同的对象值下。
注意:将此处的案例包装在一个对象中比使用大量案例进行切换要好。
检查下面的代码片段(用 es6 编写),看看我们如何返回特定扩展的特定键。
我从这个 git repo 获得了扩展列表
// 包含不同扩展名的不同图标的对象 const icons = { "music": ["mp3", "m4a", "ogg", "acc", "flac","m3u", "wav"], "video “:[“mp4”,“webm”,“mkv”,“avi”,“mov”,“m4v”,“mpeg”],“图像”:[“jpg”,“gif”,“png”,“ jpeg"、"tif"、"psd"、"raw"、"ico"]、"存档":["zip"、"rar"、"tar"、"dmg"、"jar"]、"3d 文件“:[“3ds”、“dwg”、“obj”、“dae”、“skp”、“fbx”]、“文本”:[“doc”、“rtf”、“txt”、“odt”、“ tex"], "矢量图形":["ai", "svg"], "pdf": ["pdf"], "data": ["xml", "csv", "xls"] } const get_icon_Key =( icons_object,file_extention) => { // 对于每个键,我们检查值是否包含在值列表中 let key = Object.keys(icons_object).find( k=> icons[k].find( //在这个级别,我们检查扩展是否存在于特定对象值的数组中,即'music','video' ... icons_ext => icons_ext === file_extention) //如果我们发现它意味着这是我们的关键正在寻找 ? true: false); return key } console.log(`mp3扩展的图标为:=> ${get_icon_Key(icons,"mp3")}`) console.log(`mp4扩展的图标为:=> ${get_icon_Key(图标,"mp4")}`)
真的很直接。
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"
我知道我迟到了,但是您对我今天制作的这个 EMCMAScript 2017 解决方案有什么看法?它处理多个匹配,因为如果两个键具有相同的值会发生什么?这就是我创建这个小片段的原因。
当有一个匹配时,它只返回一个字符串,但当有多个匹配时,它返回一个数组。
let object = { Nine_eleven_was_a_inside_job: false, javascript_isnt_useful: false } // 复杂、肮脏但有用。处理多场比赛,这是主要的困难。 Object.prototype.getKeyByValue = function (val) { let array = [];让数组2 = []; // 获取对象中的所有键。 for(const [key] of Object.entries(this)) { if (this[key] == val) { // 将它们放在第一个数组中。 array.push(key) } } // 列出第一个数组的所有值。 for(key of array) { // "如果数组中的某个key与函数(val)中传入的值相等,则表示'val'对应。" if(this[key] == val) { // 推送所有匹配项。 array2.push(key); } } // 检查数组的长度。 if (array2.length < 2) { // 如果小于 2,只返回单个值,不在数组中。返回数组2[0]; } else { // 如果大于等于 2,则返回整个数组。返回数组2; } } /* 不处理多个匹配项的基本方法。 let getKeyByValue = function (object, val) { for(const [key, content] of Object.entries(object)) { if (object[key] === val) { return key } } } */ console.log( object.getKeyByValue(false))
把事情简单化!
您不需要通过复杂的方法或库过滤对象,Javascript 有一个名为 Object.values 的内置函数。
例子:
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
keys()
实现了密钥集。function getKeyByValue(object, value) { return Object.keys(object).filter(key => object[key] === value); }
BiMap
或等效项(Alethes 的答案)通常是解决更广泛问题的有效 O(1) 方法,但即使是一次性的,也至少可以使用for in
进行迭代并在找到匹配项时中断,而不是提前创建一个完整的键数组,从而导致最好的情况比最坏的情况更好。也就是说,O(position) 而不是 O(size)。 (这个页面上唯一比 O(size) 更糟糕的答案是愚蠢的 JSON 答案。)