【问题标题】:How to find Key value from an object based on the value passed如何根据传递的值从对象中查找键值
【发布时间】:2019-09-28 11:11:12
【问题描述】:

感谢您的宝贵时间。

我在 JavaScript 中有以下对象:

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

现在我想解析一个特定的值,如果该值存在,我想返回与其关联的键。假设我正在传递'value3',它应该返回key1;如果通过value5,它应该返回我key2等等。

使用 Javascript 实现它的最佳方法是什么,请记住执行时间。我试过使用像indexOfsubstr这样的sting操作函数;但我相信不是最有效的。

TIA。

【问题讨论】:

  • indexOf 如果 value2 有 "value1,value22,value3" 可能会失败,因此您可能需要首先通过映射它们来拆分值,然后在数组上使用 indexOf。到那时,我想反向方法会更聪明,通过创建一个键值对映射,其中键是值,值是所需的键。

标签: javascript arrays json search


【解决方案1】:

对我来说,最快和最简洁的方法是结合 Array.prototype.find()String.prototype.includes() 对源对象 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'));

ps 虽然 filter()reduce()forEach() 将遍历整个数组,但 find() 在找到匹配项时立即停止,因此,如果性能很重要,我会坚持后者

【讨论】:

  • 我不认为这会因为简洁而获胜。
  • 有更短的吗?
  • ...即使可能有一个,我怀疑它会同时更快
  • 在不拆分值的情况下,我对这里的准确性持怀疑态度。假设您在第一个数组上得到“value55”,在第二个数组上得到“value5”,测试“value5”将返回第一个数组而不是实际答案。所以答案不正确吧?
  • 现在它没有,我相信它值得一票。
【解决方案2】:

includes 可用于检查数组中是否存在值。 Object.keys 可用于迭代和检查匹配。

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

【讨论】:

    【解决方案3】:

    应该这样做。只需使用 Object.entries 和过滤器来查找包含您要查找的值的条目。 (也可以找到多个具有所需值的对象)

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

    可能想在尝试访问之前检查Object.entries(obj).filter((o) => o[1].split(',').includes(find)) 的返回值,以防它不返回任何内容。像这样:

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

    【讨论】:

      【解决方案4】:

      这是一种稍微不同的方法,它会生成一个映射,其中键实际上是原始 values 对象的值。 生成的地图将是一种快速查找。只是为了让事情清楚只要您需要进行大量查找,此解决方案就很有效。对于单个唯一的查找,此解决方案的效率较低,因为构建 hashmap 需要比仅查找单个值更多的时间。 但是,一旦地图准备好,通过键获取值会非常快,所以如果您需要稍后获取多个值,这种方案会更适合使用案例。

      这可以使用Object.entriesObject.values 来完成。下面的代码中提供了进一步的解释。

      下面的代码(尽管不是必需的)还将避免indexOf 出现限制情况,例如在常规字符串上搜索“value9”而不是“value9999”,这实际上可以与 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

      【讨论】:

      • Obviously, 1000 条记录不足以胜过其他记录。连微弱的拖钓阴影都没有,你真的相信它会在某个时候更快吗?
      • 你没有明白我的意思:如果你不需要找到一个键而是多个键,由于复杂性降低了,它会显着提高。如果您需要查找很多键,由于索引,该方法比常规查找更有效。
      • 现在我明白了,我必须同意你的观点,因为搜索 2 个值 O(n) 会比 O(n2) 快很多,尤其是在大型输入数据上。跨度>
      【解决方案5】:

      您可以尝试迭代对象中的每个值,然后将值拆分为每个逗号,然后检查该值是否在返回的数组中,如下所示:

      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)

      编辑:更改循环以提高效率,并将代码提取到函数

      【讨论】:

      • return 不会完全按照这里的预期做,尽管方法可能是正确的。
      • return 将停止forEach(),不是吗?无论如何,这是我想要的结果。
      • 不,不会。如果您删除return,sn-p 将执行完全相同的操作,内部的函数会为每次迭代执行显式或隐式返回。 forEach 没有“常规”的停止方式,但如果你真的想的话,你可以抛出异常。
      • @KobanDavis 实际上并没有,你不能以这种方式“直接”破坏 foreach,但它仍然是一个解决方案,它涵盖了很多情况。我最终只会添加逗号不存在的情况。
      • @briosheje "a".split(",") 给你一个单元素数组,不需要单独的大小写。
      【解决方案6】:

      根据您的搜索,您可以在遍历对象后使用indexOf。 这是一个老式的方法:

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

      或者您可以使用Object.keys()filter() 方法并获取返回数组的索引0。

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

      【讨论】:

      • 如果你寻找value3,这将失败"value1,value2,value33"
      • @briosheje OP 没有提到它必须完全匹配。他们必须澄清在这种情况下应该发生什么。 indexOf 看起来更安全
      • @adiga 我认为这是隐含的,但我可能错了。
      【解决方案7】:

      Lodash 有一个名为 findKey 的函数,它接受对象和一个函数来确定真实性:

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

      【讨论】:

      • 我错过了问题下的lodash标签吗?
      • 是否在重新发明轮子?根本没有要求仅根据问题中列出的标签进行响应。来自帮助中心:“仔细阅读问题。具体来说,问题是什么?确保你的答案提供了 - 或可行的替代方案。答案可以是“不要那样做”,但它还应该包括“试试这个”。任何让提问者朝着正确方向前进的答案都是有帮助的,但请尝试在答案中提及任何限制、假设或简化。简洁是可以接受的,但更全面的解释会更好。”
      • 'reinventing' 基本上只需要一行简单的代码(查看我的答案),并且不需要随身携带用于发明轮子的工具箱...
      【解决方案8】:

      使用Object.entriesArray.prototype.filter 来获得所需的密钥。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-01-20
        • 1970-01-01
        • 1970-01-01
        • 2016-08-30
        • 1970-01-01
        • 1970-01-01
        • 2018-09-01
        相关资源
        最近更新 更多