Reputation: 2255
Given the following object
var obj = {'low': [1, 2, 3], 'medium': [4, 5, 6], 'high': [7, 8, 9, 10]}
is it possible, using Object.keys
(no loop), to get key (low/medium/high) by one of the corresponding values?
Upvotes: 1
Views: 117
Reputation: 808
You're looking for a different data structure than a basic object. Have a look at the bidirectional map. This is a data strucure that allows you to look up values by their key, and keys by their value.
I can recommend this implementation. It's part of mnemonist, which has a bunch of handy data structures for different use cases!
import BiMap from 'mnemonist/bi-map';
const obj = {'low': [1, 2, 3], 'medium': [4, 5, 6], 'high': [7, 8, 9, 10]};
const lookupTable = BiMap.from(obj);
console.log(lookupTable.get('low'))
// > [1,2,3]
console.log(lookupTable.inverse.get([1,2,3]))
// > 'low'
Upvotes: 0
Reputation: 4616
You can do it with Object.keys, Object.values, Array#findIndex and Array#some.
var obj = {'low': [1, 2, 3], 'medium': [4, 5, 6], 'high': [7, 8, 9, 10]};
function mySearch(obj,search) {
return Object.keys(obj)[(Object.values(obj).findIndex(el => el.some(val => val===search)))];
}
console.log(mySearch(obj, 5));
console.log(mySearch(obj, 8));
Upvotes: 0
Reputation: 33726
It's not possible to do this without a custom approach, there are a lot of ways for accomplishing what you want.
This approach uses the Proxy
object to find the key by the accessed property and keeps the entries to be able to provide quick access.
const obj = {'low': [1, 2, 3], 'medium': [4, 5, 6], 'high': [7, 8, 9, 10]},
decorate = (o) => {
const entries = Object.entries(o);
return new Proxy(o, {
get(_, accessedProperty) {
let [key] = (entries.find(([_, values]) => values.includes(+accessedProperty)) || []);
return key;
}
});
},
decoratedObj = decorate(obj);
console.log(decoratedObj[1]);
console.log(decoratedObj[4]);
console.log(decoratedObj[10]);
console.log(decoratedObj[11]);
Upvotes: 0
Reputation: 332
You can define a function to return the key according to the value passed. the function uses Object.keys and Array.find()
var obj = {'low': [1, 2, 3], 'medium': [4, 5, 6], 'high': [7, 8, 9, 10]};
const findKeyByValue = (value)=>{
return Object.keys(obj).find(key => obj[key].find(element => element === value))
}
console.log(findKeyByValue(8))
Upvotes: 0
Reputation: 651
Maybe something like this:
var obj = {'low': [1, 2, 3], 'medium': [4, 5, 6], 'high': [7, 8, 9, 10]};
function getKey(n) {
return Object.keys(obj).find(k => obj[k].includes(n));
}
Upvotes: 3
Reputation: 41893
If you would really like to avoid for loop
, you can use Array#reduce
instead.
var obj = {'low': [1, 2, 3], 'medium': [4, 5, 6], 'high': [7, 8, 9, 10]};
const fn = (value, arr) =>
Object.entries(arr)
.reduce((s, [key, a]) => (a.indexOf(value) > -1 ? key : s), null);
console.log(fn(7, obj));
console.log(fn(1, obj));
Upvotes: 1