Flutter中如何按条件从字符串列表提取指定区间的目标字符串
Flutter 提取发票消费条目实现方案
实现思路
核心是靠两个固定锚点定位消费条目区间,不需要依赖固定索引位置,适配不同发票的内容长度差异:
- 起始锚点:包含
CHECK #(账单编号)的行,消费内容从该行的下一行开始 - 结束锚点:包含
SUB-TOTAL(小计)的行,消费内容到该行的前一行结束 - 截取区间后额外过滤空行等无效内容,输出最终结果
完整实现代码
/// 从ML Kit识别的发票字符串列表中提取消费条目 List<String> extractConsumeItems(List<String> rawOcrList) { int? startPos; int? endPos; // 遍历列表定位两个锚点的索引 for (int i = 0; i < rawOcrList.length; i++) { final String currentLine = rawOcrList[i].trim(); // 匹配CHECK #行,兼容前后多余空格、大小写差异 if (currentLine.contains(RegExp(r'CHECK\s*#', caseSensitive: false))) { startPos = i + 1; } // 匹配SUB-TOTAL行,兼容SUB TOTAL、SUBTOTAL等常见写法、大小写差异 if (currentLine.contains(RegExp(r'SUB[\s-]?TOTAL', caseSensitive: false))) { endPos = i; break; // 找到结束锚点直接终止遍历,节省性能 } } // 锚点合法性校验,避免索引越界崩溃 if (startPos == null || endPos == null || startPos >= endPos) { return []; } // 截取区间内容,过滤空字符串、全空格的无效行 return rawOcrList .sublist(startPos, endPos) .where((line) => line.trim().isNotEmpty) .toList(); }
效果验证
用提供的示例数据测试:
void main() { const List<String> rawOcrResult = [ 'Line', 'Restaurant & Cafe', 'Abdomen', '079900000000', 'VAT# 16669304', 'TABLE', '19-06 2022 12:37', 'CHECK # 289395 TABLE#', '2 MINERAL WATER', '1 HOT CHOCOLATE', '1 TURKISH COFFEE DOUBLE', 'SUB-TOTAL', ]; final List<String> items = extractConsumeItems(rawOcrResult); print(items); // 输出结果: [2 MINERAL WATER, 1 HOT CHOCOLATE, 1 TURKISH COFFEE DOUBLE],和预期完全一致 }
适配说明
- 正则匹配默认关闭大小写敏感,适配OCR识别可能出现的字母大小写偏差
- 兼容
SUB TOTAL/SUBTOTAL/sub-total等不同的小计写法,以及CHECK #这类多空格的识别误差 - 自带异常兜底,遇到识别结果缺失锚点的极端情况不会触发程序崩溃,直接返回空列表
- 自动过滤区间内的空白行,避免OCR识别产生的空内容混入最终结果
内容的提问来源于stack exchange,提问作者Faris Shomali
相关产品推荐
相关产品推荐

