使用数组反向查找对象

Reverse lookup object with array

本文关键字:查找 对象 数组      更新时间:2023-09-26

假设我有一个像这样的对象

resourceMap = {
    "a": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
    "b": [11, 12],
    "c": [21, 23],
    "d": [54, 55, 56, 57, 510]
};

判断resourceId = 21是否为"c"的最佳方法是什么?

我们不知道钥匙的名称或钥匙的数量。它只匹配一次:意味着21将只属于一个密钥"c"

我正在考虑循环使用所有键并执行indexOf(),但我觉得它不够"优雅"。

我可以使用Undercore,但尽量避免使用Angular或jQuery,或者只是普通的Javascript。

在JavaScript中为对象提供数字属性名是完全可以接受的。我们可以利用这一点来构建第二个对象,以反向映射所有内容。这将使查找成本低廉。

var reverseMap = {};
for(var propName in resourceMap)
{
    var numsArr = resourceMap[propName];
    numsArr.forEach(function(num){
        reverseMap[num]=propName;
    });
}
console.log(reverseMap[54]); //'d'

http://jsfiddle.net/y11sbgbv/

构建反向映射也可以更"功能性"地完成(例如,不使用副作用),如下所示:

var reverseMap2 = Object.keys(resourceMap).reduce((acc, propName) =>          
  resourceMap[propName].reduce((a, num) => {
    a[num] = propName;
    return a;
  }, acc), {});

预处理为不同的查找表

var revMap = []; // or var revMap = {};
Object.keys(resourceMap).forEach(function(key) { 
    resourceMap[key].forEach( function (ind) {
         revMap[ind] = key;   
    });
});
console.log(revMap[21])

或按需查询:

resourceMap = { "a": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], "b": [11, 12], "c": [21, 23], "d": [54, 55, 56, 57, 510] };
function findMapKey (map, ind) {
    var match = null;
    Object.keys(map).some(function(key) {
        var test = map[key].indexOf(ind)!==-1;
        if (test) { 
            match = key; 
        } 
        return test;
    });
    return match;
}
console.log(findMapKey(resourceMap, 21));

它看起来像是对值进行了排序,所以您可以首先查看每个数组的最新值是否大于您要搜索的值,一旦找到,就查找值本身。

for(var propName in resourceMap)
{
    var array = resourceMap[propName];
    var lastNum = array[array.length-1];
    if(lastNum == 21 || (lastNum > 21 && array.indexOf(21) > -1))
    {
       console.log(propName)
       break;
    }
}

除非您正在处理大量数据,否则您的想法很好:

    var resourceMap = {
      "a": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
      "b": [11, 12],
      "c": [21, 23],
      "d": [54, 55, 56, 57, 510]
    };
    /**
     * @return resource's group, or false if no matching group is found
     */
    var getResourceGroup = function(res) {
      for (var i in resourceMap) {
        if (resourceMap[i].indexOf(res) > -1) {
          return i;
        }
      }
      return false;
    }
    console.log(getResourceGroup(21));

我理解对优雅的渴望,我在自己的作品中也努力做到这一点。但这很简单,很容易得到支持,而且假设您的数据集不是很大,速度也相对较快。

如果您要多次调用该函数,那么第一次通过该函数构建反向字典可能是值得的,这样您就可以使用它来加快未来的查找速度。问题是,如果确实有大量数据,那么您将在内存中构建一个相当大的数据结构。也许没什么大不了的,但值得考虑。

尝试

resourceMap = {
    "a": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
    "b": [11, 12],
    "c": [21, 23],
    "d": [54, 55, 56, 57, 510]
};
var getKey = function(val, _key) {
$.each(resourceMap, function(k, v) {
  if ($.inArray(val, v) != -1) {
    _key = k
  }  
})
return _key
};
getKey(21)

jsfiddlehttp://jsfiddle.net/guest271314/gbnzmq51/