[每日一练]患某种疾病的患者,正则表达式的匹配

时间:2024-06-08 07:29:04

该题目来源于力扣:

1527. 患某种疾病的患者 - 力扣(LeetCode)

题目要求:

患者信息表: Patients

+--------------+---------+
| Column Name  | Type    |
+--------------+---------+
| patient_id   | int     |
| patient_name | varchar |
| conditions   | varchar |
+--------------+---------+
在 SQL 中,patient_id (患者 ID)是该表的主键。
'conditions' (疾病)包含 0 个或以上的疾病代码,以空格分隔。
这个表包含医院中患者的信息。

查询患有 I 类糖尿病的患者 ID (patient_id)、患者姓名(patient_name)以及其患有的所有疾病代码(conditions)。I 类糖尿病的代码总是包含前缀 DIAB1 。

按 任意顺序 返回结果表。

查询结果格式如下示例所示。

示例 1:

输入:
Patients表:
+------------+--------------+--------------+
| patient_id | patient_name | conditions   |
+------------+--------------+--------------+
| 1          | Daniel       | YFEV COUGH   |
| 2          | Alice        |              |
| 3          | Bob          | DIAB100 MYOP |
| 4          | George       | ACNE DIAB100 |
| 5          | Alain        | DIAB201      |
+------------+--------------+--------------+
输出:
+------------+--------------+--------------+
| patient_id | patient_name | conditions   |
+------------+--------------+--------------+
| 3          | Bob          | DIAB100 MYOP |
| 4          | George       | ACNE DIAB100 | 
+------------+--------------+--------------+
解释:Bob 和 George 都患有代码以 DIAB1 开头的疾病。

思路流程:

首先,题目要求condition列要求包含字符串“DBAB1”开头,我们会想到用正则表达式的^字符表达字符串的开头。但是condition列包含 多种疾病,当“DBAB1”不属于第一个疾病位置时,^字符会失效。所以我们要用 \b内容\b 形式来进行边界匹配(每个疾病之间会用空格隔开),然后使用.str.coutains()来进行匹配。

注意,在应用.str.coutains()时要添加:regex=True 用来表达传入的参数是正则表达式。

代码实现:

import pandas as pd

def find_patients(patients: pd.DataFrame) -> pd.DataFrame:
    #\b表示字符串的边界。只能在正则表达式中使用
    result=r'\bDIAB1'
    return patients[patients['conditions'].str.contains(result,regex=True)]

思路2:

有时候我们对正则表达式不太熟悉,那么不用正则表达式也可以,不过相对麻烦,因为我们要考虑糖尿病在第一个位置或者不在第一个位置的情况。

代码实现:

import pandas as pd

def find_patients(patients: pd.DataFrame) -> pd.DataFrame:
    return patients[patients["conditions"].str.startswith('DIAB1') | patients["conditions"].str.contains(' DIAB1',regex=False)]

拓展(关于pandas自带的执行字符串匹配和操作。):

  1. .str.endswith(suffix[, na]):类似于 .str.startswith(),但是检查字符串是否以指定的后缀结尾。

  2. .str.contains(pat[, case, flags, na, regex]):检查字符串是否包含指定的子字符串或模式。它可以通过正则表达式进行模式匹配。

  3. .str.match(pat[, case, flags, na]):检查字符串是否与指定的正则表达式模式匹配。与 .str.contains() 不同,它只匹配字符串的开头。

  4. .str.extract(pat[, flags, expand]):根据正则表达式模式从字符串中提取匹配的子字符串。可以用于从复杂的文本中提取特定模式的信息。

  5. .str.findall(pat[, flags]):查找字符串中所有与正则表达式模式匹配的子字符串,并返回它们的列表。

  6. .str.startswith()仅用于检查字符串是否以给定的前缀开头。

总结:

大部分匹配内容的时候还是建议使用正则表达式。以上的两个思路正则表达式执行的速度稍微快一点,是311ms,而非正则表达式的执行速度是323ms,而且非正则表达式的方法要把所有的情况都要考虑并且写出来,相对繁琐。