[英]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 版本对我来说似乎很慢,这个更快!
更快,因为:
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.