【问题标题】:Filter a JavaScript array of strings matching a sequence of characters过滤与字符序列匹配的 JavaScript 字符串数组
【发布时间】:2018-11-27 22:22:06
【问题描述】:

如何有效地过滤与字符序列匹配的字符串数组,以便字符可以匹配字符串中的任何位置,但按照它们的使用顺序?

这是编辑器和 IDE 中常见的一种快速过滤文件名的功能。

在附加的图片链接中查看过滤器的实际使用说明。

这不是JavaScript autocomplete without external library 的重复,因为这里的要求之一是用户输入“Caz”以匹配“Cangzhou”,这在此问题的答案中有所解释,但在其他问题的答案中没有。

【问题讨论】:

  • 未尝试提出解决方案。如果我有我会张贴它。我不知道从哪里开始。
  • 只要谷歌搜索“Javascript 自动完成”就会给你很多资源。以stackoverflow.com/questions/11404855/…w3schools.com/howto/howto_js_autocomplete.asp 为例
  • 根据你的框架,有很多选项可以自动完成基于异步服务器的信息和本地信息。
  • 感谢谷歌的建议。我在提出建议并看到 Robby Comlissen 的答案后做了。但大多数都是子字符串匹配的示例,并且在设置 css 和 html 时充满了太多噪音。我还没有看到使用 ES6 + 构建正则表达式来执行匹配的想法。

标签: javascript


【解决方案1】:

这个简单的例子使用正则表达式和Array.prototype.filter()

var strings = ["Cairo", "Casablanca", "Cangzhou", "Carcas"]; // Your array of things to filter

function disp(matches) {
 
    // Displays the filtered results on the page
    var results = document.getElementById("suggestions");
    results.innerHTML = matches.join("<br>");

}

function regExpTest(inputString, regex) {
    
    // Checks to see if what the user typed matches any items in gucciArray
    return regex.test(inputString);

}

function typeKey(event) { // This function is supposed to be called whenever the user types a letter in the text box
      
    var textTyped = event.target.value; // What the user typed in the text box;

    var filter = new RegExp(textTyped.split('').join('.*'), 'i'); // Matches anything with the characters that the user typed, in order, with any characters inbetween them
  
    // Filter the array
    // Returns a new array containing the items from the old array that pass the RegExp test
    var filteredArray = strings.filter(s => regExpTest(s, filter));

    // Display the filtered results on the page
    disp(filteredArray);

}

disp(strings);
<html>
    <head>
    </head>
    <body>

        Type here: <input type="text" onkeyup="typeKey(event);">
        <br>
        List of matches:
        <div id="suggestions"></div>

    </body>
</html>

disp 是可选的。它仅适用于交互式代码 sn-p。如果您想获取稍后使用的值,请将typeKey 中的最后一行替换为return newArray;

【讨论】:

【解决方案2】:

这实际上比看起来要简单。此外,当前接受的解决方案实际上并不能始终如一地工作。

您只需要构造一个在搜索字符串的每个字符之间接受 0 个或多个字符的正则表达式。

const values = ['Belgium', 'Brest', 'Britian']
const query = 'Be'

// /.*b.*e.*/
const re = RegExp(`.*${query.toLowerCase().split('').join('.*')}.*`)

// [ 'Belgium', 'Brest' ]
const matches = values.filter(v => v.toLowerCase().match(re))

【讨论】:

    【解决方案3】:

    我认为这应该非常接近。答案尝试构建一个正则表达式,以使字符按照它们在搜索词中出现的顺序进行匹配。

    const values = ['Brussels', 'Cairo', 'Casablanca', 'Cangzhou', 'Caracas',
        'Los Angeles', 'Osaka'];
    
    const match = (s) => {
      const p = Array.from(s).reduce((a, v, i) => `${a}[^${s.substr(i)}]*?${v}`, '');
      const re = RegExp(p);
      
      return values.filter(v => v.match(re));
    };
    
    console.log(match('Ca'));    // Cairo, Casablanca, Cangzhou, Caracas
    console.log(match('Caz'));   // Cangzhou
    console.log(match('as'));    // Casablanca, Caracas
    console.log(match('aa'));    // Casablanca, Caracas, Osaka

    【讨论】:

      【解决方案4】:

      这是一个例子。

      为了减少意外错误,您应该将输入值限制为您希望他们键入的值。

      var all = ['test','string','array','example'];
      
      function getMatch(arr, str){
        var reg = new RegExp(str.split('').join('.*'), 'i');
        
        return arr.filter(function(item) {
          if (item.match(reg)) {
            return item;
          }
        });
      }
      
      function search(value){
        document.getElementById("result").innerHTML = getMatch(all, value);
      }
      <input type="text" onkeyup="search(this.value)">
      <br />
      <span id="result"></span>

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-12-05
        • 1970-01-01
        • 1970-01-01
        • 2021-10-08
        相关资源
        最近更新 更多