a_pdd_test.py 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. import re
  2. def extract_quantity_and_unit(text: str):
  3. """
  4. 从药品选择文本中提取数量与单位。
  5. 优先级:
  6. 1. 选几发几 → (1, '盒')
  7. 2. 显式数字/中文数字 + 单位(如 10盒, 三粒)
  8. 3. 特殊模式 *数字.../盒 或 *数字.../瓶(如 0.5g*15袋/盒)→ (1, 盒/瓶) # 仅当没有显式数量时
  9. 4. 数字ml/单位(如 100ml/盒)→ (1, 单位)
  10. 5. 单独数字ml(如 120ml)→ (1, '瓶')
  11. """
  12. unit_pattern = '瓶|盒|支|只|个|袋|包|粒|片|贴|罐|桶|条|板|枚|颗|管|套|丸|锭|听'
  13. def chinese_to_int(s: str):
  14. if s.isdigit():
  15. return int(s)
  16. chinese_map = {'一':1,'二':2,'三':3,'四':4,'五':5,
  17. '六':6,'七':7,'八':8,'九':9,'十':10,
  18. '百':100,'千':1000,'万':10000}
  19. if len(s) == 1:
  20. return chinese_map.get(s, 0)
  21. if len(s) == 2 and s[0] in chinese_map and s[1] == '十':
  22. return chinese_map[s[0]] * 10
  23. if s == '十':
  24. return 10
  25. return 1
  26. # 1. 选几发几
  27. if re.search(r'选\d+发\d+|选[一二三四五六七八九十]+发[一二三四五六七八九十]+', text):
  28. return (1, '盒')
  29. # 2. 显式数字/中文数字 + 单位(优先级最高)
  30. explicit_match = re.search(
  31. r'([一二三四五六七八九十百千万]+|\d+)\s*/?\s*(' + unit_pattern + r')',
  32. text
  33. )
  34. if explicit_match:
  35. num_str, unit = explicit_match.groups()
  36. quantity = chinese_to_int(num_str)
  37. return (quantity, unit)
  38. # 3. 特殊模式:*数字.../盒 或 *数字.../瓶(无显式数量时使用)
  39. special_match = re.search(r'\*\s*\d+\s*.*?/(盒|瓶)(?:装)?', text, re.IGNORECASE)
  40. if special_match:
  41. unit = special_match.group(1)
  42. return (1, unit)
  43. # 4. 数字ml/单位
  44. implicit_match = re.search(r'[\d\.]+\s*ml\s*/\s*(' + unit_pattern + r')', text, re.I)
  45. if implicit_match:
  46. unit = implicit_match.group(1)
  47. return (1, unit)
  48. # 5. 单独数字ml → 1瓶
  49. if re.search(r'[\d\.]+\s*ml', text, re.I):
  50. return (1, '瓶')
  51. return (None, None)
  52. test_cases = [
  53. "0.5g*15袋/盒", # 无显式数量 → 1盒
  54. "0.33g*24/粒/盒", # → 1盒
  55. "0.5g*100/片/瓶", # → 1瓶
  56. "10mg*20/粒/瓶", # → 1瓶
  57. "已选: 2盒", # → 2盒
  58. "已选择: 25ml/瓶", # → 1瓶
  59. "0.5g*15袋/盒装", # → 1盒
  60. "0.5g*15袋", # 无/盒/瓶 → 15袋
  61. "0.5g*15袋/盒 10盒", # 有显式10盒 → 10盒 ✅
  62. "10盒 0.5g*15袋/盒", # → 10盒
  63. "一支", # → 1支
  64. "两粒", # → 2粒
  65. ]
  66. for ex in test_cases:
  67. q, u = extract_quantity_and_unit(ex)
  68. print(f"{ex:30s} -> {q}{u if u else ''}")