该题目来源于力扣:
1517. 查找拥有有效邮箱的用户 - 力扣(LeetCode)
题目要求:
表: Users
+---------------+---------+
| Column Name | Type |
+---------------+---------+
| user_id | int |
| name | varchar |
| mail | varchar |
+---------------+---------+
user_id 是该表的主键(具有唯一值的列)。
该表包含了网站已注册用户的信息。有一些电子邮件是无效的。
编写一个解决方案,以查找具有有效电子邮件的用户。
一个有效的电子邮件具有前缀名称和域,其中:
- 前缀 名称是一个字符串,可以包含字母(大写或小写),数字,下划线
'_'
,点'.'
和/或破折号'-'
。前缀名称 必须 以字母开头。 - 域 为
'@leetcode.com'
。
以任何顺序返回结果表。
结果的格式如以下示例所示:
示例 1:
输入:
Users 表:
+---------+-----------+-------------------------+
| user_id | name | mail |
+---------+-----------+-------------------------+
| 1 | Winston | winston@leetcode.com |
| 2 | Jonathan | jonathanisgreat |
| 3 | Annabelle | bella-@leetcode.com |
| 4 | Sally | sally.come@leetcode.com |
| 5 | Marwan | quarz#2020@leetcode.com |
| 6 | David | david69@gmail.com |
| 7 | Shapiro | .shapo@leetcode.com |
+---------+-----------+-------------------------+
输出:
+---------+-----------+-------------------------+
| user_id | name | mail |
+---------+-----------+-------------------------+
| 1 | Winston | winston@leetcode.com |
| 3 | Annabelle | bella-@leetcode.com |
| 4 | Sally | sally.come@leetcode.com |
+---------+-----------+-------------------------+
解释:
用户 2 的电子邮件没有域。
用户 5 的电子邮件带有不允许的 '#' 符号。
用户 6 的电子邮件没有 leetcode 域。
用户 7 的电子邮件以点开头。
关于pandas的正则表达式:
--正则表达式的匹配元素的形式:
- 普通字符:表示匹配自身的字符,例如字母、数字、标点符号等。
- 元字符 :具有特殊含义的字符,例如
.
、^
、$
等。 - 字符类 :用方括号
[]
表示,匹配括号内的任意一个字符。 - 重复匹配 :使用
*
、+
、?
等符号表示重复匹配的次数或范围。 - 边界匹配 :使用
^
和$
分别表示字符串的开头和结尾。 - 分组和引用 :使用圆括号
()
表示一个子表达式,可以对子表达式进行分组和后向引用。
--常用的正则表达式方法:
- str.contains(): 用于检查每个元素是否包含指定的模式。
- str.replace(): 用于替换匹配的内容。
- str.extract(): 用于从每个元素中提取匹配的内容。
- str.match(): 用于检查每个元素是否以指定的模式开头。
- str.findall(): 用于找到所有匹配的内容。
--正则表达式的相关功能:
^:表示一个字符串或行的开头
[a-z]:表示一个字符范围,匹配从 a 到 z 的任何字符。
[0-9]:表示一个字符范围,匹配从 0 到 9 的任何字符。
[a-zA-Z]:这个变量匹配从 a 到 z 或 A 到 Z 的任何字符。请注意,你可以在方括号内指定的字符范围的数量没有限制,您可以添加想要匹配的其他字符或范围。
[^a-z]:这个变量匹配不在 a 到 z 范围内的任何字符。请注意,字符 ^ 用来否定字符范围,它在方括号内的含义与它的方括号外表示开始的含义不同。
[a-z]*:表示一个字符范围,匹配从 a 到 z 的任何字符 0 次或多次。
[a-z]+:表示一个字符范围,匹配从 a 到 z 的任何字符 1 次或多次。
.:匹配任意一个字符。
\.:表示句点字符。请注意,反斜杠用于转义句点字符,因为句点字符在正则表达式中具有特殊含义。还要注意,在许多语言中,你需要转义反斜杠本身,因此需要使用\\.。
$:表示一个字符串或行的结尾。
题目要求拆解:
首先第一个字符必须是字符串形式的字母;后续的字符可以是字符串也可以是数字,后续同样也包括 "_""-""."的字符串。同时,要求完全匹配网站的域:"@leetcode.com"
所以我们要用到的形式有:
重复匹配: 使用*
、+
、?
等符号表示重复匹配的次数或范围;还有字符类 :用方括号[]
表示,匹配括号内的任意一个字符;元字符 :具有特殊含义的字符,例如.
、^
、$
。
要用到的方法有:
str.match(): 用于检查每个元素是否以指定的模式开头。
代码实现:
python
import pandas as pd
def valid_emails(users: pd.DataFrame) -> pd.DataFrame:
#注意:"-"字符串有特殊的含义,要想把它作为字符串进行匹配,要放在字符的最前边或最后边
#在正则表达式中@是一个特殊的字符,所以@leetcode要用转移符号框起来,最后用特殊连接符.将com连接,实现域的完全匹配。
#第一个列表表示第一个字符匹配的区域,第二个带*的列表表示后续可以出现多次的字符串区域
result=r'[a-zA-Z][a-zA-Z0-9_.-]*\@leetcode\.com'
return users[users['mail'].str.match(result)]