该题目来源于力扣:
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自带的执行字符串匹配和操作。):
-
.str.endswith(suffix[, na])
:类似于.str.startswith()
,但是检查字符串是否以指定的后缀结尾。 -
.str.contains(pat[, case, flags, na, regex])
:检查字符串是否包含指定的子字符串或模式。它可以通过正则表达式进行模式匹配。 -
.str.match(pat[, case, flags, na])
:检查字符串是否与指定的正则表达式模式匹配。与.str.contains()
不同,它只匹配字符串的开头。 -
.str.extract(pat[, flags, expand])
:根据正则表达式模式从字符串中提取匹配的子字符串。可以用于从复杂的文本中提取特定模式的信息。 -
.str.findall(pat[, flags])
:查找字符串中所有与正则表达式模式匹配的子字符串,并返回它们的列表。 -
.str.startswith()仅用于检查字符串是否以给定的前缀开头。
总结:
大部分匹配内容的时候还是建议使用正则表达式。以上的两个思路正则表达式执行的速度稍微快一点,是311ms,而非正则表达式的执行速度是323ms,而且非正则表达式的方法要把所有的情况都要考虑并且写出来,相对繁琐。