SUDIPTO
SUDIPTO

Reputation: 21

How to find Key value from an object based on the value passed

Thanks for your time.

I have the following object in JavaScript:

{
  "key1":"value1,value2,value3",
  "key2":"value4,value5,value6"
} 

Now I want to parse for a specific value and if the value exists, I want to return the key associated with it. Suppose that I am passing 'value3', it should return key1; if passing value5, it should return me key2 and so on.

What is the best way to implement it using Javascript, keeping in mind the execution time. I have tried using sting manipulation functions like indexOf, substr; but not most effective I believe.

TIA.

Upvotes: 2

Views: 1084

Answers (8)

Yevhen Horbunkov
Yevhen Horbunkov

Reputation: 15530

To me, the fastest and most concise way of doing that would be the combination of Array.prototype.find() and String.prototype.includes() thrown against source object entries:

const src={"key1":"value1,value2,value3","key2":"value4,value5,value6"};

const getAkey = (obj, val) => (Object.entries(obj).find(entry => entry[1].split(',').includes(val)) || ['no match'])[0];

console.log(getAkey(src, 'value1'));
console.log(getAkey(src, 'value19'));

p.s. while filter(), or reduce(), or forEach() will run through the entire array, find() stops right at the moment it finds the match, so, if performance matters, I'd stick to the latter

Upvotes: 2

Dani Vijay
Dani Vijay

Reputation: 2258

includes can be used to check whether a value is present in an array. Object.keys can be used for iteration and checking for the match.

function findKey(json, searchQuery) {
  for (var key of Object.keys(json)) if (json[key].split(',').includes(searchQuery)) return key;
}

const json = {
  "key1": "value1,value2,value3",
  "key2": "value4,value5,value6"
}

console.log(findKey(json, 'value5'))

Upvotes: 1

John
John

Reputation: 579

This should do it. Just uses Object.entries and filters to find the entries that contain the value you're looking for. (Can find more than one object that has the desired value too)

var obj = {
	"key1": "value1,value2,value3",
	"key2": "value4,value5,value6"
};

var find = 'value2';
var key = Object.entries(obj).filter(([k, v]) => v.split(',').includes(find))[0][0];

console.log(key);

Might want to check the return value of Object.entries(obj).filter((o) => o[1].split(',').includes(find)) before trying to access it, in case it doesn't return anything. Like so:

var obj = {
	"key1": "value1,value2,value3",
	"key2": "value4,value5,value6"
};

function findKey(objectToSearch, valueToFind) {
	var res = Object.entries(objectToSearch).filter(([key, value]) => value.split(',').includes(valueToFind));
	if(res.length > 0 && res[0].length > 0) {
		return res[0][0];
	}
	return false;
}

console.log(findKey(obj, 'value5'));

Upvotes: 1

briosheje
briosheje

Reputation: 7446

Here is a slightly different approach that will generate a map where the key is actually the value of your original values object. The generated map will be a sort of fast lookup. Just to make things clear this solution is efficient as long as you need to do a lot of lookups. For a single, unique lookup this solution is the less efficient, since building the hashmap requires much more time than just looking up for a single value. However, once the map is ready, acquiring values through keys will be incredibly fast so, if you need to later acquire multiple values, this solution will be more suitable for the use case.

This can be accomplished using Object.entries and Object.values. Further explanations are available in the code below.

The code below (despite not required) will also take care of avoiding indexOf with limit cases like searching 'value9' over 'value9999' which, on a regular string, would actually work with indexOf.

const values = {
  "key1":"value1,value2,value3",
  "key2":"value4,value5,value6",
  "key3":"value444,value129839,value125390", // <-- additional test case.
  "key4": "value9" // <-- additional test case.
};

const map = Object.entries(values).reduce((acc, [key, value]) => {
  // If the value is invalid, return the accumulator.
  if (!value) return acc;
  // Otherwise, split by comma and update the accumulator, then return it.
  return value.split(',').forEach(value => acc[value] = key), acc;
}, {});

// Once the map is ready, you can easily check if a value is somehow linked to a key:
console.log(map["value444"]); // <-- key 3
console.log(map["value9"]); // <-- key 4
console.log(map["Hello!"]); // undefined

Upvotes: 3

Kobe
Kobe

Reputation: 6446

You can try iterating over each value in your object and then splitting the value on each comma, then checking if the value is in the returned array like so:

const myObj = {"key1":"value1,value2,value3","key2":"value4,value5,value6"}
 

function findKeyByValue(obj, value) {
    for (var key in myObj) {
    	const valuesArray = myObj[key].split(',')
        if (valuesArray.includes(value)) {
            return key
        }
    }
}

const key = findKeyByValue(myObj, 'value5') // returns 'key2'
console.log(key)

EDIT: Changed loop for efficiency, and extracted code to function

Upvotes: 1

Radonirina Maminiaina
Radonirina Maminiaina

Reputation: 7004

Based on your search, you can use indexOf after looping through your object. Here's an old school method:

var obj = {
  "key1":"value1,value2,value3",
  "key2":"value4,value5,value6"
}

function search (str) {
  for (var key in obj) {
var values = obj[key].split(',');
if (values.indexOf(str) !== -1) return key
  }
  return null;
}

console.log(search('value1'))
console.log(search('value6'))

Or you can use Object.keys() with filter() method and get the index 0 of the returned array.

var obj = {
  "key1":"value1,value2,value3",
  "key2":"value4,value5,value6"
}

function search (str) {
  return Object.keys(obj).filter((key) => {
  	const values = obj[key].split(',');
    if (values.indexOf(str) !== -1) {
    	return key
    }
  })[0]
}

console.log(search('value1'))
console.log(search('value6'))

Upvotes: 1

sloppypasta
sloppypasta

Reputation: 1126

Lodash has a function for this called findKey which takes the object and a function to determine truthiness:

obj = { 'key1': 'value1, value2, value3', 'key2': 'value4,value5,value6' }
_.findKey(obj, val => val.includes('value3'))
# 'key1'
_.findKey(obj, val => val.includes('value5'))
# 'key2'

Upvotes: 1

Kunal Mukherjee
Kunal Mukherjee

Reputation: 5853

Use Object.entries with Array.prototype.filter to get what the desired key.

const data = {
  "key1": "value1,value2,value3",
  "key2": "value4,value5,value6"
};

const searchStr = 'value3';

const foundProp = Object.entries(data).filter(x => x[1].indexOf(searchStr) !== -1);

let foundKey = '';

if (foundProp && foundProp.length) {
  foundKey = foundProp[0][0];
}

console.log(foundKey);

Upvotes: 0

Related Questions