繁体   English   中英

将多个子字符串匹配到一个字符串

[英]Matching multiple substrings to a string

我有一个应用程序,用户在其中输入文本,然后将此文本发送到服务器并返回包含此文本的单词数组。

在此处输入图片说明

但是正如您所看到的,当有超过 1 个匹配项时,问题就开始了。 这是我当前的代码:

state.input !== '' && vocabularyItems && (vocabularyItems.map((vocabularyItem, index) => {
      const regex = new RegExp(input, 'gi');
      const results = vocabularyItem.matchAll(regex);

      const tmp = [];
      console.log(vocabularyItem);
      for (const match of results) {
        console.log(match);
        let currentLoop = vocabularyItem.slice(0, match.index);

        currentLoop += '<strong className="tt-highlight">';

        currentLoop += vocabularyItem.slice(match.index, match.index + input.length);

        currentLoop += '</strong>';

        currentLoop += vocabularyItem.slice(match.index + input.length, vocabularyItem.length);

        tmp.push(currentLoop);
      }
      console.table(tmp);

      return (
        <div
          id={index}
          className={`override-strong tt-suggestion tt-selectable ${cursor === index && 'tt-cursor'}`}
          onMouseDown={handleClick}
          key={index}
          dangerouslySetInnerHTML={{ __html: tmp }}
        />
      );
    }))

这里有一些 HTML 代码示例

1.
<strong className="tt-highlight">En</strong>kelkind

2.
<strong className="tt-highlight">En</strong>gagement
Engagem<strong className="tt-highlight">en</strong>t

如您所见,它在仅出现一次时起作用,但在存在多个匹配项时重复该单词。 我怎么能最终得到类似的东西

<strong>en</strong>gagem<strong>en</strong>t?

gagem EN T'

我忘了补充说我需要保留这个案例

这是一种使用string.replace

 const list = [ 'end', 'England', 'engagement' ] const boldify = (search) => { return (string) => string.replace(new RegExp(search, 'gi'), '<strong>$&</strong>') } document.body.innerHTML = list.map(boldify('en')).join('<br>')


编辑:经过一段时间的思考,并看到接受的答案,我想推动香草 JS 版本有更完整的东西。 而且,React 版本对我来说似乎很慢这个更快!

更快,因为:

  • 它使用原生 JavaScript
  • 它使用正确的 dom 操作(没有innerHTML

 'use strict' const list = [ 'end', 'England', 'engagement', 'Ken Bogard', 'Venom', 'Engagement' ] const boldify = (search) => { return (string) => { const div = document.createElement('div') const parts = string.split(new RegExp(`(?=${search})|(?<=${search})`, 'gi')) div.append( ...parts.map(part => { if (part.toUpperCase() !== search.toUpperCase()) return part const strong = document.createElement('strong') strong.innerText = part return strong }) ) return div } } const contains = (search) => { search = search.toUpperCase() return (string) => string.toUpperCase().indexOf(search) >= 0 } const refreshSuggestions = () => { // Fast removal of children. while (suggestions.firstChild) suggestions.removeChild(suggestions.firstChild) // nothing to do if (searchInput.value.length == 0) return const newSuggestions = list.filter(contains(searchInput.value)) .map(boldify(searchInput.value)) suggestions.append(...newSuggestions) } searchInput.addEventListener('input', refreshSuggestions)
 <input id="searchInput" list="suggestions"> <div id="suggestions"> </div>

首先,我建议使用,例如:

const results = vocabularyItems.filter(word => word.toLowerCase().includes(input.toLowerCase()))

用于不区分大小写的词汇查找。

接下来,我将以稍微不同的方式突出显示这场比赛。 我将建议的选项分成几部分(匹配搜索输入和不匹配的),然后分别设置它们的样式:

const parts = suggestion.split(new RegExp(`(?=${match})|(?<=${match})`, 'gi'))
...
parts.map((part,key) => {
          const style = part.toLowerCase() == match.toLowerCase() ? 'bold' : 'normal'
          return <span style={{fontWeight:style}} {...{key}}>{part}</span>
        })

我认为假设您构建自动完成搜索输入是足够安全的,因此您可能会发现使用下面的快速演示(不包括所有样式):

 //dependencies const { render } = ReactDOM, { useState } = React //vocabulary const vocabulary = ['engagement', 'Bentley', 'English', 'seven', 'Engagement'] //suggested option component const SuggestedOption = ({suggestion, match}) => { const parts = suggestion.split(new RegExp(`(?=${match})|(?<=${match})`, 'gi')) return ( <div> { parts.map((part,key) => { const style = part.toLowerCase() == match.toLowerCase() ? 'bold' : 'normal' return <span style={{fontWeight:style}} {...{key}}>{part}</span> }) } </div> ) } //autocomplete component const SearchBar = () => { const [suggestions, setSuggestions] = useState([]), [inputValue, setInputValue] = useState(''), onInput = input => { setInputValue(input) setSuggestions(vocabulary.filter(word => input.length && word.toLowerCase().includes(input.toLowerCase()))) } return ( <div> <input onKeyUp={e => onInput(e.target.value)} /> <div > { suggestions.map((suggestion,key) => <SuggestedOption {...{key,suggestion,match:inputValue}} />) } </div> </div> ) } render( <SearchBar />, document.getElementById('root') )
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"></script><div id="root"></div>

编辑 - Yevgen 的回答比这个好得多。

如果我正确理解你想要什么,一个简单的循环可以实现这一点:

var array = ["end","engagement","Engagement","england","enough","not this","or this"];

function filterArray(array, id) {
    var returnArray = [];
  for (var i = 0; i < array.length; i++) {
    value = array[i];
    if (value.includes(id)) {
        returnArray.push(value);
    }
    }
    return returnArray;
}

var filteredArray = filterArray(array,"en");
console.log(filteredArray);

如果您想确保重复(其中 Engagement 的大小写导致重复),您可以在推送到数组之前将字符串设置为小写,并在再次推送之前检查数组是否存在字符串。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM