You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 15:21:25