AbsoluteBeginner
AbsoluteBeginner

Reputation: 2255

Using Object.keys with array of values

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

Answers (6)

thijsfranck
thijsfranck

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

Sascha A.
Sascha A.

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

Ele
Ele

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

Jithin Zachariah
Jithin Zachariah

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

Raukaute
Raukaute

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

kind user
kind user

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

Related Questions