前言
伴随着业务的迭代, 在数据量有大概四五万情况下, 需要实现实时搜索, 也就是在输入框输入时实时匹配搜索结果, 调用接口不太现实, 所以本地实现实时匹配. 类似于搜索通讯录联系人功能.
数据结构一般是一个很大的数组, 例:
[
{
"searchMainCondition": "10A片式保险丝",//搜索条件一
"searchOtherCondition": "other"//搜索条件二
},
{
"searchMainCondition": "10PK1045皮带",
"searchOtherCondition": "other"
},
{
"searchMainCondition": "ABS",
"searchOtherCondition": "other"
},
{
"searchMainCondition": "侧围窗内板(右)",
"searchOtherCondition": "other"
}
]
实时搜索的过程可以根据searchMainCondition和searchOtherCondition等等其他条件同时进行模糊匹配
中文转拼音及简单分词
对原始数据做简单的处理, 对searchMainCondition进行全拼转为completeSpellingSearchterm, 由于待搜索completeSpellingSearchterm一般比较短, 只进行加空格达到简单的分词效果. 对searchMainCondition进行简拼转为logogramShorteningSearchterm,这样只需输入 'CWCNB' ---可以搜索到--- '侧围窗内板(右)'
[
{
"searchMainCondition": "10A片式保险丝",//搜索条件一
"searchOtherCondition": "other",//搜索条件二
"completeSpellingSearchterm": "10APian Shi Bao Xian Si",//转为拼音
"logogramShorteningSearchterm": ""//汉字首字母
},
{
"searchMainCondition": "10PK1045皮带",
"searchOtherCondition": "other",
"completeSpellingSearchterm": "10PK1045Pi Dai",
"logogramShorteningSearchterm": ""
},
{
"searchMainCondition": "ABS",
"searchOtherCondition": "other",
"completeSpellingSearchterm": "ABS",
"logogramShorteningSearchterm": "ABS"
},
{
"searchMainCondition": "侧围窗内板(右)",
"searchOtherCondition": "other",
"completeSpellingSearchterm": "Ce Wei Chuang Nei Ban (You )",
"logogramShorteningSearchterm": "CWCNB"
}
]
汉字转拼音可以使用该框架中文转拼音, 核心代码块
if ([ChineseInclude isIncludeChineseInString:dic[@"searchMainCondition"]]) {
NSString *completeSpellingSearchterm = [PinYinForObjc chineseConvertToPinYin:dic[@"searchMainCondition"]];
NSStrin *glogogramShorteningSearchterm = [PinYinForObjc chineseConvertToPinYinHead:dic[@"searchMainCondition"]];
}
实时搜索引擎PermissiveResearch
这时用到一个容错模糊搜索引擎PermissiveResearch可以下载修改后的版本PermissiveResearchModified
- 导入PermissiveResearchModified类库
- PermissiveAlignementMethods.c Identity and Type 更改为Objective-C Source
- 设置代理
[[PermissiveResearchDatabase sharedDatabase] setDatasource:self];
[[PermissiveResearchDatabase sharedDatabase] setDelegate:self];
- 文本输入发生变化时我们开始实现文本实时检索
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
[self epcsGetSearchTermString:textField.text];
}
- PermissiveResearchDatasource加载搜索源
#pragma mark - PermissiveResearchDatasource
- (void)rebuildDatabase
{
NSArray *dataArr = [self epcsGetSearchTermDataArr];
[[PermissiveResearchDatabase sharedDatabase] addObjects:dataArr forKeyPaths:@[@"completeSpellingSearchterm"]];//根据转为拼音后的关键词搜索
}
- (NSArray *)epcsGetSearchTermDataArr
{
NSArray *sandboxpath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString *filePath = [[sandboxpath objectAtIndex:0] stringByAppendingPathComponent:@"epcsGetSearchTerm.plist"];
NSArray *arrMain = [NSArray arrayWithContentsOfFile:filePath];
return arrMain;
}
- PermissiveResearchDelegate
#pragma mark - PermissiveResearchDelegate
-(void)epcsGetSearchTermString:(NSString *)searchedString
{
searchedKeywordsString = [[NSString alloc] initWithString:searchedString];//缓存中文搜索词
if ([ChineseInclude isIncludeChineseInString:searchedString]) {
searchedString = [PinYinForObjc chineseConvertToPinYin:searchedString];
}
[[PermissiveResearchDatabase sharedDatabase] searchString:searchedString withOperation:ScoringOperationTypeExact];
}
-(void)searchCompletedWithResults:(NSArray *)results
{
NSMutableArray *resultArr = @[].mutableCopy;
if (results && results.count > 0) {
NSMutableArray *perfectMatchArr = @[].mutableCopy;
NSMutableArray *prefixArr = @[].mutableCopy;
NSMutableArray *otherMatchArr = @[].mutableCopy;
for (int i = 0; i < results.count; i++) {
id obj = [results objectAtIndex:i];//results为PermissiveObject对象
if ([obj isKindOfClass:[PermissiveObject class]]) {
PermissiveObject *permissiveObj = (PermissiveObject *)obj;
NSDictionary *dict = [permissiveObj refencedObject];
NSString *dicCurrentSearchterm = dict[@"searchterm"];
if ([dicCurrentSearchterm isEqualToString:searchedKeywordsString]) {
[perfectMatchArr addSafeObject:dict];//和搜索词完全匹配的
} else if ([dicCurrentSearchterm hasPrefix:searchedKeywordsString]) {
[prefixArr addSafeObject:dict];//以搜索词开头的
} else {
[otherMatchArr addSafeObject:dict];
}
}
}
//调整搜索结果顺序
[resultArr addObjectsFromSafeArray:perfectMatchArr];
[resultArr addObjectsFromSafeArray:prefixArr];
[resultArr addObjectsFromSafeArray:otherMatchArr];
}
matchedSubDataArr = resultArr;
//刷新数据
}
- 清空数据源
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
[[PermissiveResearchDatabase sharedDatabase] removeAllObjects];
}