一个高性能的字符串非连续搜索函数库
English | 📑中文
完整示例 请点此查看
- 易于使用
- 高性能
- 小于 1kb
- 支持 TypeScript
# via npm
npm install sdm2
# via yarn
yarn add sdm2
在Node.js
, esModule
, Browser
引入
// commonjs(Node.js)
var { match, filterMap } = require('sdm2').default;
// esModule
import { match, filterMap } from 'sdm2';
Browser
<script src="https://unpkg.com/sdm2"></script>
也许你会用它在路径搜索,树型控件选项搜索,checkbox 项搜索,或其他一些本地数据的非连续字符串搜索,它都可以满足你,请参见下面的示例。
const ret = match('src/views/home.jsx', 'shojsx');
/* ret => {
origin: 'src/views/home.jsx',
str: 'src/views/home.jsx',
strArr: ['src/views/home.jsx'],
position: [0, [10, 11], [15, 17]],
indexes: [0, 10, 11, 15, 16, 17]
}
*/
// 未匹配则返回null
const ret = match('src/views/home.jsx', 'ZZZZ');
// ret => null
返回字段解释
字段名 | 描述 |
---|---|
origin | 被查找字符串,match 函数的第一个参数原始值 |
str | 匹配关键字后通过onMatched 转换后的字符串,如果未指定onMatched ,它的值和 origin 相同 |
strArr | 关键字已匹配字符串与未匹配字符串的切分数组,如果指定了onMatched ,匹配部分为onMatched 转换后的值 |
position | 匹配的关键字所在被查找字符串的位置,如果连续匹配到多个关键字,会通过[startIndex, endIndex] 表示 |
indexes | 匹配的关键字所在被查找字符串的位置,与position 不同的是,即使连续匹配到多个关键字也会一一列出 |
如果被查找的字符串嵌套在对象内,可以使用matchStr
返回被查找的字符串。
const ret = match({ name: 'src/views/home.jsx' }, 'shojsx', {
matchStr: obj => obj.name
});
/* ret => {
origin: { name: 'src/views/home.jsx' },
str: 'src/views/home.jsx',
strArr: ['src/views/home.jsx'],
position: [0, [10, 11], [15, 17]],
indexes: [0, 10, 11, 15, 16, 17]
}
*/
利用未匹配值为 null
过滤数组。
const matchedStrings = [
'src/views/home.jsx',
'src/views/about.jsx',
'src/views/ad.jsx',
];
const ret = matchedStrings.filter(strItem => match(strItem, 'srchom.X', { ignoreCase: true });
/* ret => ['src/views/home.jsx'] */
使用onMatched
函数转换匹配字符串,可以高亮匹配到的关键字。
onMatched
会在每次匹配到一部分关键字时触发,它的参数分别为匹配的关键字和查找的原始值。
import { match } from 'sdm2';
const ret = match('src/views/home.jsx', 'shojsx', {
onMatched: (matchedStr, origin) => `<span class="highlight">${matchedStr}</span>`
});
/* ret => {
origin: 'src/views/home.jsx',
str: '<span class="highlight">s</span>rc/views/<span class="highlight">ho</span>me.<span class="highlight">jsx</span>',
strArr: [
'<span class="highlight">s</span>',
'rc/views/',
'<span class="highlight">ho</span>',
'me.',
'<span class="highlight">jsx</span>'
],
position: [0, [10, 11], [15, 17]],
indexes: [0, 10, 11, 15, 16, 17]
}
*/
如果对于字符串数组,我们可以使用filterMap
同时进行过滤和转换字符串。filterMap
将会先过滤出符合查找关键字的项,再调用onMap
转换已匹配项
import { filterMap } from 'sdm2';
const matchedStrings = ['src/views/home.jsx', 'src/views/about.jsx', 'src/views/ad.jsx'];
const ret = filterMap(matchedStrings, 'shojsx', {
onMatched: (matchedStr, originStr) => `<span class="highlight">${matchedStr}</span>`,
onMap: (matchedInfo, index) => matchedInfo.str
});
/* ret => ['<span class="highlight">s</span>rc/views/<span class="highlight">ho</span>me.<span class="highlight">jsx</span>']
*/
jsx 语法高亮
可能你不喜欢使用dangerouslySetInnerHTML
(react)或v-html
(vue)来高亮关键字,在 jsx 中,你还可以在onMatched
中返回虚拟 dom,并在onMap
中返回已经切分好的数组,这更符合 UI 框架的使用习惯:
const ret = filterMap(matchedStrings, 'shojsx', {
onMatched: (matchedStr, originStr) => <span class="highlight">${matchedStr}</span>,
onMap: (matchedInfo, index) => matchedInfo.strArr
});
/* ret => [
VNode {
class: 'highlight',
children: 's'
},
'rc/views/',
VNode {
class: 'highlight',
children: 'ho'
},
'me.',
VNode {
class: 'highlight',
children: 'jsx'
}
]
你不需担心性能问题,每一个被搜索字符串都只会被对比一次,因此保证了高性能。下面是随机字符串的性能测试结果。
关键字符串为 50 位随机字符串
字符串数量 | 单字符串长度 | 忽大小写 | 性能 |
---|---|---|---|
1000 | 5000 | ✅ | 19ms |
1000 | 5000 | ❌ | 16ms |
5000 | 5000 | ✅ | 42ms |
5000 | 5000 | ❌ | 39ms |
10000 | 5000 | ✅ | 101ms |
10000 | 5000 | ❌ | 84ms |
如果您在使用 sdm2 时遇到困难,无论是 bug,还是新功能,都可以 点此提交