优化正则表达式以过滤数千个HTML选择选项

背景

我为HTML select元素开发了一个基于jQuery的穿梭小部件 ,因为我找不到一个最低限度编码的小部件 ,并提供了一个补偿变音符号的正则表达式filter。

问题

当几个条目添加到select ,正则表达式filter会慢慢爬行。 您可以看到问题如下:

  1. 浏览到: http : //jsfiddle.net/U8Xre/2/
  2. 单击结果面板中的输入字段。
  3. 键入任何正则表达式(例如, ^a.*ai )。

我相信罪魁祸首潜伏在这里:

 var options = $src.empty().scrollTop( 0 ).data( "options" ); var search = $.trim( $input.val() ); var regex = new RegExp( search, 'gi' ); var len = options.length; var $html = $(document.createElement( 'option' )); for( var i = 0; i < len; i++ ) { var o = options[ i ]; if( o.text.dediacritics().match( regex ) !== null ) { $src.append( $html.clone().text( o.text ).val( o.value ) ); } } $src.css( 'width', $input.width() + 4 ); 

$src是源$('#select')String.prototype.dediacritics定义为小提琴。 上面的代码针对每个按键运行。 还有一个相关的片段:

 // Create a copy of the source options to use when matching the regex. var $options = []; $src.find( "option" ).each( function() { $options.push( { value: $(this).val(), text: $(this).text() } ); }); $src.data( "options", $options ); 

这将从源列表中复制选项,但只运行一次。 (这会在传递选项时导致重复错误,但将上述代码添加到input事件处理程序中会使缓冲区更慢。)

如何使代码几乎实时地在最多5,000个单词的列表上执行正则表达式过滤?

谢谢!

我猜想更难的工作是重复调用dediacritics() (有许多正则表达式替换)而不是搜索(尽管我没有进行任何分析)。 因此,您应该缓存这些去变质字符串并仅通过它们进行搜索。 顺便说一句, test通常比match更快。

此外,您应该避免尽可能多的DOM操作 – 在清空并重新附加整个选项列表onkeypress时,您有很多这样的操作。

 // once: var options = [], src = $src[0]; // or whatever to get the DOM element $.each( src.options, function() { options.push( { el: this, text: $(this).text().dediacritics(), hidden:false } ); }); // you might put it on the element via .data(), but need not // onkeypress: var regex = new RegExp( $.trim($input.val()), 'i' ); var curEl = src.firstChild; for (var i=0; i 

演示 :这非常快(“实时”),但是在调用dediacritics() 5000次时,您可以感受到构造options数组dediacritics()时间。

我建议你

  • 创建一个多行字符串,其中包含所有选项名称的列表,每个选项名称都在一个单独的行中
  • 将regex应用于此多行字符串,以通过删除不匹配的行来过滤其内容
  • 使用匹配的行更新html作为select元素的选项

一个小评论,如果你没有使用正则表达式匹配的结果,那么你应该使用正则表达式测试:

  if( o.text.dediacritics().match( regex ) !== null ) { 

使用测试:

  if( regex.test(o.text.dediacritics()) ) {