0

我需要用javascript或 jQuery 替换字符串中的所有特殊字符。
我确信有更好的方法来做到这一点。
但我目前没有任何线索。
有人有想法吗?

function Unaccent(str) {
    var norm = new Array('À','Á','Â','Ã','Ä','Å','Æ','Ç','È','É','Ê','Ë','Ì','Í','Î','Ï', 'Ð','Ñ','Ò','Ó','Ô','Õ','Ö','Ø','Ù','Ú','Û','Ü','Ý','Þ','ß', 'à','á','â','ã','ä','å','æ','ç','è','é','ê','ë','ì','í','î','ï','ð','ñ', 'ò','ó','ô','õ','ö','ø','ù','ú','û','ü','ý','ý','þ','ÿ');
    var spec = new Array('A','A','A','A','A','A','A','C','E','E','E','E','I','I','I','I', 'D','N','O','O','O','0','O','O','U','U','U','U','Y','b','s', 'a','a','a','a','a','a','a','c','e','e','e','e','i','i','i','i','d','n', 'o','o','o','o','o','o','u','u','u','u','y','y','b','y');
    for (var i = 0; i < spec.length; i++) {
        str = replaceAll(str, norm[i], spec[i]);
    }
    return str;
}

function replaceAll(str, search, repl) {
    while (str.indexOf(search) != -1) {
        str = str.replace(search, repl);
    }
    return str;
}
4

3 回答 3

4

这是一个使用查找图的版本,它比嵌套循环更有效:

function Unaccent(str) {
    var map = Unaccent.map;       // shortcut
    var result = "", srcChar, replaceChar;
    for (var i = 0, len = str.length; i < len; i++) {
        srcChar = str.charAt(i);
        // use hasOwnProperty so we never conflict with any 
        // methods/properties added to the Object prototype
        if (map.hasOwnProperty(srcChar)) {
            replaceChar = map[srcChar]
        } else {
            replaceChar = srcChar;
        }
        result += replaceChar;
    }
    return(result);
}

// assign this here so it is only created once
Unaccent.map = {'À':'A','Á':'A','Â':'A'};   // you fill in the rest of the map

工作演示:http: //jsfiddle.net/jfriend00/rRpcy/

仅供参考,谷歌搜索“重音折叠”返回许多其他实现(许多类似,但也有一些使用正则表达式)。


这是一个性能更高的版本(快 2.5 倍),它可以对重音字符进行直接索引查找,而不必进行对象查找:

function Unaccent(str) {
    var result = "", code, lookup, replaceChar;
    for (var i = 0, len = str.length; i < len; i++) {
        replaceChar = str.charAt(i);
        code = str.charCodeAt(i);
        // see if code is in our map
        if (code >= 192 && code <= 255) {
            lookup = Unaccent.map.charAt(code - 192);
            if (lookup !== ' ') {
                replaceChar = lookup;
            }
        }
        result += replaceChar;
    }
    return(result);
}

// covers chars from 192-255
// blank means no mapping for that char
Unaccent.map = "AAAAAAACEEEEIIIIDNOOOOO OUUUUY  aaaaaaaceeeeiiiionooooo  uuuuy y";

工作演示:http: //jsfiddle.net/jfriend00/Jxr9u/

这个 jsperf中,字符串查找版本(第二个示例)大约快 2.5 倍。

于 2012-09-24T16:25:41.973 回答
1

您可以准备数组的键值对类型,并通过 jquery 遍历该数组。

例子 :

function Unaccent(str) {
   var replaceString = {'À':'A','Á':'A','Â':'A'}; // add more 

   $.each(replaceString, function(k, v) {
      var regX = new RegExp(k, 'g');    
      str = str.replace(regX,v);
   });
}

工作演示

祝你好运 !!

于 2012-09-24T16:37:14.207 回答
1

使用对象作为映射是个好主意,但考虑到要替换的字符数,预初始化对象可能是个好主意,这样每次函数获取时都不必重新初始化运行(假设您不止一次运行该函数):

var Unaccent = (function () {
    var charMap = {'À':'A','Á':'A','Â':'A','Ã':'A','Ä':'A' /** etc. **/};
    return function (str) {
        var i, modified = "", cur;
        for(i = 0; i < str.length; i++) {
            cur = str.charAt(i);
            modified += (charMap[cur] || cur);
        }
        return modified;
    };
}());

这会将函数的繁重工作提前加载到页面加载时间(如果您愿意,您可以进行一些修改以将其延迟到第一次调用该函数)。但这会占用实际函数调用的一些处理时间。

无论如何,某些浏览器实际上可能会优化这部分,因此您可能看不到任何好处。但在较旧的浏览器上(性能更受关注),您可能会看到预处理字符映射的一些好处。

于 2012-09-24T16:38:07.097 回答