Ответ 1
с библиотекой Underscore.js
:
var hash = {
foo: 1,
bar: 2
};
(_.invert(hash))[1]; // => 'foo'
У меня довольно простой объект JavaScript, который я использую как ассоциативный массив. Есть ли простая функция, позволяющая мне получить ключ для значения, или мне нужно выполнить итерацию объекта и найти его вручную?
с библиотекой Underscore.js
:
var hash = {
foo: 1,
bar: 2
};
(_.invert(hash))[1]; // => 'foo'
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);
}
const map = {"first" : "1", "second" : "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
и вместо этого передать объект в нее.
Как сказано, итерация необходима. Например, в современном браузере вы можете иметь:
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);
Способ 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'
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.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
Очистите прототип .
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'
Нетерабельное решение
Основная функция:
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"
Я создал бимап-библиотеку (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"
Получение сопоставления значений ключей одинаково быстро в обоих направлениях. Нет никаких дорогостоящих обходов объекта/массива под капотом, поэтому среднее время доступа остается постоянным независимо от размера данных.
Поскольку значения уникальны, должно быть возможно добавить значения в качестве дополнительного набора ключей. Это можно сделать со следующим ярлыком.
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"
Это предполагает, что между ключами и значениями нет общих элементов.
Или, еще проще - создайте новый объект с ключами и значениями в том порядке, в котором вы хотите, и посмотрите на этот объект. У нас были конфликты, используя коды прототипов выше. Вам не нужно использовать функцию String вокруг ключа, что необязательно.
newLookUpObj = {};
$.each(oldLookUpObj,function(key,value){
newLookUpObj[value] = String(key);
});
Здесь просто для любопытства, которое оно приносит вам...
Если вы уверены, что ваш объект будет иметь только строковые значения, вы действительно можете исчерпать себя, чтобы вызвать эту реализацию:
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]);
Может быть, есть что-то полезное, чтобы оторваться отсюда...
Надеюсь, это вас забавляет.
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;
}
Это небольшое расширение для метода Underscorejs и вместо этого использует Lodash:
var getKeyByValue = function(searchValue) {
return _.findKey(hash, function(hashValue) {
return searchValue === hashValue;
});
}
FindKey будет искать и возвращать первый ключ, который соответствует значению.
Если вы хотите использовать последнее совпадение, вместо этого используйте FindLastKey.
Обычно я рекомендую 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 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
Учитывая 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;},{})
Здесь используется решение Lodash, которое работает для объекта flat key = > value, а не вложенного объекта. Принятое предложение ответа на использование _.findKey
работает для объектов с вложенными объектами, но в этом распространенном случае это не работает.
Этот подход инвертирует объект, заменяет ключи для значений, а затем находит ключ, просматривая значение для нового (инвертированного) объекта. Если ключ не найден, возвращается false
, который я предпочитаю над undefined
, но вы можете легко поменять его на третий параметр метода _.get
в getKey()
.
// Get an object 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>
Вот мое решение в первую очередь:
Например, я предполагаю, что у нас есть объект, который содержит три пары значений:
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 (массив, значение), который принимает два параметра, которые являются объектом и значением ключа, который вы ищете. Таким образом, этот метод можно использовать повторно, и вам не нужно каждый раз вручную повторять объект, передавая только два параметра для этой функции.
Подчеркни 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}
Действительно просто.
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"
ES6 методы:
Object.fromEntries(Object.entries(a).map(b => b.reverse()))['value_you_look_for']
Еще один способ сделать это:
let key = ( Object.entries(obj).find(([k,v])=>v==value) || [] )[0];
Будь проще!
Вам не нужно фильтровать объект с помощью сложных методов или библиотек, 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