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

javascript - Reverse lookup object with array - Stack Overflow

programmeradmin3浏览0评论

Let say if I have an object like this

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]
};

What is the best way to figure out if resourceId = 21 would be "c"?

We don't know the key names or number of keys. It only matches once: meaning 21 will belong to only one key "c".

I am thinking of looping through all keys and do indexOf(), but I don't feel it's "elegant" enough.

I could use Underscore but try to avoid and go with what Angular or jQuery or just vanilla Javascript.

Let say if I have an object like this

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]
};

What is the best way to figure out if resourceId = 21 would be "c"?

We don't know the key names or number of keys. It only matches once: meaning 21 will belong to only one key "c".

I am thinking of looping through all keys and do indexOf(), but I don't feel it's "elegant" enough.

I could use Underscore but try to avoid and go with what Angular or jQuery or just vanilla Javascript.

Share Improve this question edited Oct 7, 2014 at 19:58 HP. asked Oct 7, 2014 at 17:10 HP.HP. 19.9k56 gold badges159 silver badges258 bronze badges 5
  • Are the numbers in the arrays distinct, or is it possible that a number reverse-maps to more than a single item? – spender Commented Oct 7, 2014 at 17:12
  • Either you pre-process it to be in a different format or you loop on demand. Either way Vanilla JS or underscore, you will end up doing the same thing under the covers. – epascarello Commented Oct 7, 2014 at 17:13
  • @spender says it right in the OPs question. "It only matches once:..." – epascarello Commented Oct 7, 2014 at 17:13
  • @spender the number only occurs once in each key or in all the keys. – HP. Commented Oct 7, 2014 at 17:15
  • Why is there "JSON" in the header? – Teemu Commented Oct 7, 2014 at 17:20
Add a comment  | 

5 Answers 5

Reset to default 10

It's perfectly acceptable to have numeric property names for objects in JavaScript. We can use this to our advantage to build a second object that maps everything in reverse. This will make lookups inexpensive.

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/

Building the reverseMap can also be done more "functionally" (e.g. without using side-effects) as follows:

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

Preprocess into a different look up table

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

or look up on demand:

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

It looks like values are sorted, so you can first look if the latest of each array is greater than the value you're searching for, once you find it, look for the value itself.

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

Unless you're working with a massive amount of data, your idea is fine:

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

I understand the desire for elegance, and I strive for that in my own work as well. But this is simple, easily supported, and relatively fast assuming your data set isn't huge.

If you're going to call the function multiple times, it might be worth building out the reverse dictionary the first time through the function, so that you can use that to speed up future lookups. The catch there is that if you do have a ton of data, you're going to build a fairly large data structure in memory. Probably not a big deal, but worth considering.

Try

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)

jsfiddle http://jsfiddle.net/guest271314/gbnzmq51/

发布评论

评论列表(0)

  1. 暂无评论