最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to find Key value from an object based on the value passed - Stack Overflow

programmeradmin3浏览0评论

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.

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.

Share Improve this question edited May 10, 2019 at 15:13 Intervalia 11k2 gold badges34 silver badges70 bronze badges asked May 10, 2019 at 14:08 SUDIPTOSUDIPTO 213 bronze badges 1
  • indexOf may fail if you have "value1,value22,value3" for value2 so you likely need to first split the values by mapping them, and then use indexOf on the array instead. At that point, I guess a reverse-approach would be cleverer, by creating a key-value pair map where the key is the value and the value is the desired key. – briosheje Commented May 10, 2019 at 14:15
Add a ment  | 

8 Answers 8

Reset to default 3

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 acplished 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 ma 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

To me, the fastest and most concise way of doing that would be the bination 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

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'

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'))

You can try iterating over each value in your object and then splitting the value on each ma, 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

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'));

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'))

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);

发布评论

评论列表(0)

  1. 暂无评论