Flutter多词搜索实现:如何匹配包含部分输入关键词的食谱对象
现有实现的问题
你的当前版本代码存在几个可优化的点:
- 无匹配结果时直接访问
results[0]会触发数组越界异常 - 没有做匹配优先级排序,可能优先返回匹配度更低的结果
- 没有处理大小写差异,用户输入小写关键词就可能匹配失败
- 关键词拆分后仅做任意匹配,可能出现结果和搜索意图偏差过大的情况
优化实现方案
我们可以统一大小写匹配规则,按匹配度给结果排序,优先返回匹配关键词更多、完全匹配的结果,同时增加兜底逻辑避免运行异常:
class SearchRecipe { // 无匹配结果时的兜底食谱实例,你可以根据业务需要调整兜底逻辑 final RecipeModel defaultRecipe = RecipeModel(); RecipeModel returnRecipe(String? suggestion) { // 空输入直接返回兜底 if (suggestion == null || suggestion.trim().isEmpty) return defaultRecipe; final allRecipes = Store.instance.getAllRecipes(); // 搜索关键词拆分后统一转小写,消除大小写差异 final searchKeywords = suggestion.trim().toLowerCase().split(' '); // 给所有食谱计算匹配得分,得分越高匹配度越高 final scoredRecipes = allRecipes.map((recipe) { final recipeName = recipe.recipeName?.toLowerCase() ?? ''; // 统计匹配到的关键词数量 int matchCount = searchKeywords.where((keyword) => recipeName.contains(keyword)).length; // 完全匹配的情况额外加权重,优先返回 if (recipeName == suggestion.trim().toLowerCase()) { matchCount += 10; } return MapEntry(recipe, matchCount); }).toList(); // 过滤完全不匹配的结果,按得分从高到低排序 scoredRecipes.removeWhere((entry) => entry.value == 0); scoredRecipes.sort((a, b) => b.value.compareTo(a.value)); // 有匹配结果返回得分最高的,无匹配返回兜底 return scoredRecipes.isNotEmpty ? scoredRecipes.first.key : defaultRecipe; } }
方案说明
- 自动适配大小写输入,用户不管输入大写、小写、混合大小写都能正常匹配
- 匹配优先级逻辑清晰:完全匹配的结果优先级最高,其次是匹配到更多关键词的结果,比如搜索
Garlic butter时,同时匹配两个关键词的Garlic parmesan butter会排在仅匹配单个关键词的其他食谱前面 - 覆盖了空输入、无匹配结果的边界场景,不会触发运行时崩溃
- 如果你的食谱数量很大,也可以修改为遍历一次直接取最高匹配结果,不需要全量排序,性能更好
内容的提问来源于stack exchange,提问作者user14709104
相关产品推荐
相关产品推荐

