Javascript:快速查找对象中的值(就像我们可以使用属性一样)

Posted

技术标签:

【中文标题】Javascript:快速查找对象中的值(就像我们可以使用属性一样)【英文标题】:Javascript: Quickly lookup value in object (like we can with properties) 【发布时间】:2012-06-14 00:38:42 【问题描述】:

我有一个对象,它具有用于简单编码/解码的替换值对(不是为了安全,只是为了方便;太复杂了,无法在这里全部解释)。它的形式是

var obj = x: y,
           x: y,
           ...
          ;

其中“x”是编码时的值,“y”是解码后的值。

解码很简单:我循环遍历字符串的字符,并通过括号在对象中查找charAt(i) 值:obj[ str.charAt(i) ]。 (我忽略了检查是否需要大写或小写版本(对象中的所有键/值都是小写的),但这很简单。)

要进行编码,我当然要在对象中寻找值,而不是属性。目前,我正在使用for ... in ... 循环遍历属性,并根据charAt(i) 值检查这些值。我当前的代码是:

var i, j,
    output = '',
    str = 'Hello World!',
    obj = 's':'d',
           'm':'e',
           'e':'h',
           'x':'l',
           'z':'o',
           'i':'r',
           'a':'w',
           'o':'!',
           '-':' ';
for (i = 0; i < str.length; i++) 
    for (j in obj) 
        if (Object.prototype.hasOwnProperty.call(obj, j) &&
            Object.prototype.propertyIsEnumerable.call(obj, j)) 
            if (obj[j] === str.charAt(i)) 
                output += j;
                break;
             else if (obj[j].toUpperCase() === str.charAt(i)) 
                output += j.toUpperCase();
                break;
            
        
    

alert(output);

我天生就觉得应该有一种更有效的方法来做到这一点。 (当然有一个颠倒的对象,y: x,是一种选择。但不是一个好方法。)这是最好的方法,还是有更好的方法?本质上,我希望能够像 var value = obj[prop] 那样做 var prop = obj[value]

【问题讨论】:

【参考方案1】:

预先循环一次以创建反向映射更有效:

var str = "Hello World!",
    output = '',
    map = 
      "s":"d", "m":"e",
      "e":"h", "x":"l",
      "z":"o", "i":"r",
      "a":"w", "o":"!",
      "-":" "
    ,
    reverseMap = 

for (j in map)
  if (!Object.prototype.hasOwnProperty.call(map, j)) continue
  reverseMap[map[j]] = j


output = str.replace(/./g, function(c)
  return reverseMap[c] || reverseMap[c.toLowerCase()].toUpperCase()
)

console.log(output)

您将执行map.length + str.length 操作,而不是执行str.length * map.length

【讨论】:

是的!如果可以的话,我会给你两次投票,因为这将两个建议的改进合二为一。这绝对是我接受的答案(除非有任何其他惊人的版本......)。谢谢!【参考方案2】:

反向编码器会更有意义,但您可以编写一个替换函数而不需要所有的 hasOwnProperty 等测试。

var str= 'Hello World!',
obj=
    's':'d',
    'm':'e',
    'e':'h',
    'x':'l',
    'z':'o',
    'i':'r',
    'a':'w',
    'o':'!',
    '-':' '

str= str.replace(/./g, function(w)
    for(var p in obj)
        if(obj[p]=== w) return p;
        if(obj[p]=== w.toLowerCase()) return p.toUpperCase();
    ;
    return w;
);

返回值:(字符串)Emxxz-Azixso

【讨论】:

我不知道你可以像这样传递一个函数来替换!我假设当前的 to_replace 值(/./)被传递给函数,因此 w?更优雅和可读的版本,我一定会考虑这个。 @kennebec 你仍然需要hasOwnProperty 检查以避免来自原型扩展的无关数据。声明的值将覆盖它们,但它可以返回匹配而不是在没有匹配时引发错误。 @kennebec:我同意里卡多的观点。尽管这是我自己编写的所有代码,但安全总比抱歉好。我喜欢让自己养成良好的习惯。我认为hasOwnProperty 应该足够了。我之所以有propertyIsEnumerable 是因为this info from Eloquent javascript【参考方案3】:

您可以通过编程方式(而不是手动)创建映射的反转版本并使用它。

var rev = 
for (key in obj)
    rev[obj[key]] = key

【讨论】:

你知道吗?你是个天才...... ;) 这对我来说是那些“DUH”时刻之一。手工映射绝对不是一种选择,特别是如果我希望能够扩展原始的范围。 (我见过有两个版本的相当长的键/值对的代码,想到要花多少时间输入它们并随着代码的开发进行编辑,我就感到畏缩。)【参考方案4】:

如果您正在寻找数组键,请点击此处。

https://raw.github.com/kvz/phpjs/master/functions/array/array_keys.js

function array_keys (input, search_value, argStrict) 
    var search = typeof search_value !== 'undefined', tmp_arr = [], strict = !!argStrict, include = true, key = '';

    if (input && typeof input === 'object' && input.change_key_case) 
        return input.keys(search_value, argStrict);
    

    for (key in input) 
        if (input.hasOwnProperty(key)) 
            include = true;
            if (search) 
                if (strict && input[key] !== search_value) include = false;
                else if (input[key] != search_value) include = false;
            
            if (include) tmp_arr[tmp_arr.length] = key;
        
    

    return tmp_arr;

【讨论】:

以上是关于Javascript:快速查找对象中的值(就像我们可以使用属性一样)的主要内容,如果未能解决你的问题,请参考以下文章

javaScript数组对象

二叉树(下)

JavaScript数据结构——树

JavaScript一种新的数据结构类型Map

javascript中对象属性搜索原则

JS中的加号+运算符详解