基于Vanilla JavaScript的可筛选列表:如何实现任意子串匹配?
实现任意顺序子串匹配的姓名筛选列表修改方案
嘿,这个需求我太熟了!你现在的筛选逻辑应该是用了includes()这类方法,只能匹配连续的子串,所以输入dm找不到Adam。要实现输入任意字符(只要按顺序出现在姓名里)就能匹配,核心是改成按顺序的非连续子串匹配,我给你一步步拆解怎么改:
先看原逻辑的问题
假设你原来的筛选代码大概是这样的:
// 原连续子串匹配逻辑 function filterNames(inputValue, names) { return names.filter(name => name.toLowerCase().includes(inputValue.toLowerCase()) ); }
includes()要求输入的字符串是姓名里的一段连续内容,所以dm这种不连续的组合就匹配不上。
修改后的核心逻辑
我们需要写一个辅助函数,检查输入的每个字符是否按顺序出现在姓名中(不要求连续)。直接上可复用的代码:
// 辅助函数:验证输入字符是否按顺序存在于目标姓名中 function matchesOrderedSubsequence(input, target) { const inputLower = input.trim().toLowerCase(); const targetLower = target.toLowerCase(); let inputPointer = 0; // 如果输入为空,直接返回匹配 if (!inputLower) return true; // 遍历目标姓名的每个字符 for (const char of targetLower) { // 匹配到输入的当前字符,就移动输入指针 if (char === inputLower[inputPointer]) { inputPointer++; // 输入的所有字符都匹配完成,直接返回true if (inputPointer === inputLower.length) { return true; } } } // 遍历完姓名还没匹配完所有输入字符,返回false return inputPointer === inputLower.length; } // 修改后的筛选函数 function filterNames(inputValue, names) { return names.filter(name => matchesOrderedSubsequence(inputValue, name)); }
逻辑验证示例
比如输入dm匹配Adam的过程:
- 输入转成小写是
dm,姓名转成小写是adam - 遍历
adam的第一个字符a,不匹配d,跳过 - 第二个字符
d,匹配输入的第一个字符,输入指针移到1(对应m) - 第三个字符
a,不匹配m,跳过 - 第四个字符
m,匹配输入的第二个字符,输入指针移到2,等于输入长度,返回true,所以Adam会被筛选出来
同样,输入da的时候,会匹配到adam里的d和后面的a,也能成功匹配。
结合DOM使用的完整示例
如果要和你的输入框绑定,完整可运行的代码大概是这样的:
<input type="text" id="nameFilter" placeholder="输入任意字符筛选..."> <ul id="nameList"></ul> <script> const names = ['Adam', 'Bob', 'David', 'Amanda', 'Emma']; const filterInput = document.getElementById('nameFilter'); const nameList = document.getElementById('nameList'); // 辅助匹配函数 function matchesOrderedSubsequence(input, target) { const inputLower = input.trim().toLowerCase(); const targetLower = target.toLowerCase(); let inputPointer = 0; if (!inputLower) return true; for (const char of targetLower) { if (char === inputLower[inputPointer]) { inputPointer++; if (inputPointer === inputLower.length) { return true; } } } return inputPointer === inputLower.length; } // 筛选函数 function filterNames(inputValue, names) { return names.filter(name => matchesOrderedSubsequence(inputValue, name)); } // 渲染列表 function renderFilteredList(filteredNames) { nameList.innerHTML = filteredNames.map(name => `<li>${name}</li>`).join(''); } // 初始渲染 renderFilteredList(names); // 监听输入变化 filterInput.addEventListener('input', (e) => { const filteredNames = filterNames(e.target.value, names); renderFilteredList(filteredNames); }); </script>
这样修改后,只要输入的字符是按姓名里的顺序出现的(比如dm、da、am都能匹配Adam),就能筛选出对应的姓名啦!
内容的提问来源于stack exchange,提问作者Magnetic Kode
相关产品推荐
相关产品推荐

