Dart中如何在含多词元素的两个列表中查找精确匹配的公共元素
问题
我正在开发一款可在食品食材列表中查找特定食材的APP,现有名为filtered results的食材列表,以及名为desired strings的目标食材列表。当前使用集合交集方法匹配时,commonElements返回空集合;拆分单词匹配仅能得到单个词(如"vegetable"而非"vegetable oil"),请问如何实现多词元素的精确匹配?
完整数据
filtered results
[{key: enriched corn meal (corn meal, ferrous sulfate, niacin, thiamin mononitrate, riboflavin, folic acid), vegetable oil (corn, canola, and/or sunflower 0il), cheese seasoning (whey, cheddar cheese [milk, cheese cultures, salt, enzymes], canola oil, maltodextrin [made from corn], natural and artificial flavors, salt, whey protein concentrate, monosodium glutamate, lactic acid, citric acid. artificial color [yellow 6]), and salt.}, {key: enriched corn meal (corn meal, ferrous sulfate, niacin, thiamin mononitrate, riboflavin, folic acid), vegetable oil (corn, canola, and/or sunflower 0il), cheese seasoning (whey, cheddar cheese [milk, cheese cultures, salt, enzymes], canola oil, maltodextrin [made from corn], natural and artificial flavors, salt, whey protein concentrate, monosodium glutamate, lactic acid, citric acid. artificial color [yellow 6]), and salt.}]
desired Strings
[value from home page, seed oils, sunflower oil, sunflower lecithin, sesame oil, sesamin, safflower oil, safflower oleosomes, grapeseed oil, grapeseed extract, flaxseed oil, flaxseed meal, chia seed oil, chia seed gel, pumpkin seed oil, pumpkin seed protein, hemp seed oil, hemp seed protein, poppy seed oil, poppy seed paste, mustard seed oil, mustard seed powder, cottonseed oil, cottonseed meal, vegetable oil, canola oil]
当前代码
API结果清理代码
List<String> cleanedUpStrings = filteredResults.toList() .map((entry) => entry["key"].toString().toLowerCase()) .map((s) => s.replaceAll(RegExp(r'[^\w\s,]'), ' ')) // Replace characters other than word characters, spaces, and commas .toList();
匹配代码
Set<String> lowercaseSet1 = cleanedUpStrings.map((e) => e.toLowerCase().trim()).toSet(); Set<String> lowercaseSet2 = desiredStrings.map((e) => e.toLowerCase().trim()).toSet(); Set<String> commonElements = lowercaseSet1.intersection(lowercaseSet2);
解决方案
问题根源
- 集合交集失效:
cleanedUpStrings里的每个元素是整段食材文本,而desiredStrings是单个食材名称,两者完全不相等,交集自然为空。 - 单词匹配问题:拆分单词会破坏多词食材的完整性,无法识别"vegetable oil"这类组合名称。
实现多词精确匹配的步骤
1. 优化文本清理逻辑
先把整段食材文本拆分成独立的食材项,同时保留多词结构:
List<String> cleanedIngredients = []; for (var entry in filteredResults) { String rawText = entry["key"].toString().toLowerCase(); // 替换特殊字符为空格,保留逗号用于拆分食材项 String cleanedText = rawText.replaceAll(RegExp(r'[^\w\s,]'), ' '); // 按逗号拆分食材项,去空去空格 List<String> items = cleanedText.split(',') .map((item) => item.trim()) .where((item) => item.isNotEmpty) .toList(); cleanedIngredients.addAll(items); }
2. 预处理目标食材列表
转小写并去重,过滤无效项:
Set<String> targetIngredients = desiredStrings .map((s) => s.toLowerCase().trim()) .where((s) => s.isNotEmpty && s != 'value from home page') .toSet();
3. 实现多词精确匹配
遍历清理后的食材项,直接匹配完整名称;同时处理带括号的食材,提取核心名称匹配:
Set<String> matchedIngredients = {}; for (var ingredient in cleanedIngredients) { // 直接匹配完整食材名 if (targetIngredients.contains(ingredient)) { matchedIngredients.add(ingredient); } else { // 提取括号前的核心名称(比如"vegetable oil (corn...)"取"vegetable oil") int bracketIndex = ingredient.indexOf('('); if (bracketIndex != -1) { String coreName = ingredient.substring(0, bracketIndex).trim(); if (targetIngredients.contains(coreName)) { matchedIngredients.add(coreName); } } } }
4. 处理拼写错误(可选)
针对数据里的"sunflower 0il"这类数字代替字母的错误,可在清理阶段修正:
// 在文本清理时添加拼写修正 String cleanedText = rawText.replaceAll(RegExp(r'[^\w\s,]'), ' ') .replaceAll('0il', 'oil');
最终效果
经过上述处理,能精确匹配到vegetable oil、canola oil等多词食材,同时过滤无效项,得到准确的匹配结果。
内容的提问来源于stack exchange,提问作者Dylan Bozarth
相关产品推荐
相关产品推荐

