有没有更简洁的方法来删除非字母数字字符并替换空格?
Posted
技术标签:
【中文标题】有没有更简洁的方法来删除非字母数字字符并替换空格?【英文标题】:Is there a cleaner way to remove non-alphanumeric chars and replace spaces? 【发布时间】:2013-08-22 12:57:33 【问题描述】:我想替换所有非字母数字字符,并用下划线替换空格。到目前为止,我已经使用多个正则表达式提出了这个问题,但有没有更“有效”的方法?
"Well Done!".toLowerCase().replace(/\s/, '-').replace(/[^\w-]/gi, '');
干得好
【问题讨论】:
你不需要toLowerCase()
,你的意思是破折号-
而不是下划线_
?
您可以使用函数作为第二个参数来决定任何给定匹配的替换内容:developer.mozilla.org/en-US/docs/Web/javascript/Reference/…。这将避免两次遍历字符串。这是否比许多短字符串的 JS 函数调用效率更高或更低是值得怀疑的。 (我的直觉告诉我“不”,但我不能胆大妄为地制作一个 jsperf。)
无论如何,您的代码有效,所以我不确定这是一个完全合适的问题。比如,什么会使答案“正确”?除了它是“不同的”,或者是第一个出现,或者你出于某种原因喜欢它。
@millimoose 似乎使用函数参数是一个不错的选择,我真正检查的是是否有一些更“智能”的正则表达式可以让我同时做这两个:)
@htmlr 这是一个不同的选项。我认为在您的情况下,可读性和性能都更差。你在做两件不同的事情,做两个不同的调用就足够有意义了。
【参考方案1】:
至少在其他语言中,调用正则表达式引擎的成本很高。我不确定这是否适用于 JavaScript,但这是“C 风格”的做法。我确信自己对其性能进行基准测试将是一次宝贵的学习经验。
var x = "Well Done!";
var y = "";
var c;
for (var i = 0; i < x.length; i++)
c = x.charCodeAt(i);
if (c >= 48 && c <= 57 || c >= 97 && c <= 122)
y += x[i];
else if (c >= 65 && c <= 90)
y += String.fromCharCode(c+32);
else if (c == 32 || c >= 9 && c <= 13)
y += '-';
$('#output').html(y);
有关 ASCII 代码,请参阅 http://www.asciitable.com/。这是a jsFiddle。请注意,我还实现了您的 toLowerCase()
,只需将 32 添加到大写字母即可。
免责声明
当然,我个人更喜欢可读代码,因此更喜欢正则表达式,或者使用某种strtr
函数(如果存在于JavaScript 中的话)。这个答案纯粹是为了教育。
【讨论】:
鉴于 Javascript 具有 RE 字面量,它可能不会 那么 昂贵。有可能 RE 与 JS 源一起编译,而不是每次调用它。 您的功能与操作的不完全匹配。具体来说,他想要替换空格,但您只是替换空格。\w
替换空格、制表符和换行符。
@DanielGimenez - 谢谢。我意识到了这一点,但认为转换是为了创建 slug。无论如何,我绝对应该提到它。
原来大部分被正则表达式视为空白的字符都连续放置在 ASCII 中;不确定 JavaScript 是否包含 \f
和 \v
作为空白字符,但答案已更新为包含所有字符。【参考方案2】:
注意: 我想我可以用一个正则表达式提出一个更快的解决方案,但我做不到。下面是我失败的方法(你可以从失败中吸取教训),以及性能测试的结果,以及我的结论。
效率可以通过多种方式来衡量。如果您想减少调用的函数数量,则可以使用单个正则表达式和一个函数来处理替换。
([A-Z])|(\s)|([^a-z\d])
REY
第一组将应用toLowerCase()
,第二组将替换为-
,第三组将不返回任何内容。我最初对第 1 组和第 3 组使用+
量词,但考虑到文本的预期性质,删除它会导致更快的执行。 (感谢 acheong87)
'Well Done!'.replace(/([A-Z])|(\s)|([^a-z\d])/g, function (match, $0, $1)
if ($0) return String.fromCharCode($0.charCodeAt(0) + 32);
else if ($1) return '-';
return '';
);
jsFiddle
性能
我的方法表现最差:
Acheong87 fastest
Original 16% slower
Mine 53% slower
jsPerf
结论
就代码开发时间而言,您的方法是最有效的,与 acheong87 方法相比的性能损失被代码可维护性、可读性和复杂性降低所抵消。除非速度是最重要的,否则我会使用你的版本。
我添加到正则表达式的可选匹配越多,性能损失就越大。除了功能减少之外,我想不出我的方法有什么好处,但这被if
语句和复杂性增加所抵消。
【讨论】:
不错;感谢基准测试;我不知道这个网站。我想知道如果你颠倒交替原子的顺序会有什么区别(因为空格是最稀有的,大写字母是第二稀有的,小写字母是最常见的)。此外,上述可能效率低下的原因之一是它需要回溯。我在 spirit 中看到您正在尝试最小化 replacements,但+
强制在测试下一个交替原子之前发生“失败的匹配”,而没有+
,立即更换。我不确定底层代码是什么样子的
在 JS 引擎中,但我想知道替换时间是否与字符数有关,而不是与调用次数有关。我刚刚编辑了您的测试以尝试进行这些修改;嗯,性能优势并没有我想象的那么大。确实是一个值得学习的好例子。 (现在编辑我的答案以包括正则表达式空白字符,i.e. [ \f\n\r\t\v]
.
@acheong87,你在这两个方面都是对的。示例文本的性质和实际用法使+
在性能方面效率低下。如果我们预计大写字母会更频繁,更改顺序也会有所帮助。以上是关于有没有更简洁的方法来删除非字母数字字符并替换空格?的主要内容,如果未能解决你的问题,请参考以下文章