处理数据时的一项基本技能是能够搜索它并找到特定的信息位。在 Python 中处理文本数据时,您可能需要获取有关其内容的一些信息:它是否包含特定的子字符串(即字符串的一部分)、该子字符串在哪里,或者它在文本中出现的次数。在本主题中,我们将学习如何做到这一点。
子串搜索算法
我们将从子字符串搜索问题开始。给定两个字符串,text和pattern ,我们需要确定在text中是否至少出现了一次pattern。解决这个问题最简单、最自然的方法是依次考虑文本中长度等于模式长度的所有子字符串,并将它们与模式本身进行比较。如果至少在一种情况下所有对应的符号都匹配,则找到该模式。如果这些尝试都没有成功,我们应该指出没有模式在文本中。下面是如何在 Python 中实现这个简单的算法:
def contains(text, pattern):
for i in range(len(text) - len(pattern) + 1):
found = True
for j in range(len(pattern)):
if text[i + j] != pattern[j]:
found = False
break
if found:
return True
return False
命名的函数contains
将两个字符串text
和pattern
, 作为输入,如果text
包含pattern
,则返回True,
否则返回False
。
在外循环的每一步for
,我们创建一个名为found
的变量并赋值为True
. 然后,在内部for
循环中,我们开始比较pattern
与当前的子字符串text
。如果至少有一个对应的符号不匹配,我们将变量设置found
为False
并中断内部循环。内部for
循环完成后,我们检查found
变量的状态。如果仍然存在True
,则表示 的每个符号都pattern
与当前子字符串匹配。在这种情况下,我们返回True
表明pattern
已找到。否则,我们进入下一次迭代并开始考虑下一个子字符串。如果没有一个比较成功,即外部for
循环完成所有迭代,函数返回False
指示pattern
未找到。
以下是如何使用此算法:
contains("abacabad", "cab") # True
contains("abacabad", "abacabad") # True
contains("aba", "") # True
contains("abacabad", "hello") # False
现在我们知道有一个子字符串搜索算法以及如何在 Python 中实现它。但是,也有解决问题的内置函数和运算符。让我们看看它们是什么。
成员检测
另一种定义字符串中是否存在特定模式的方法称为成员资格测试,它是在运算符in
和的帮助下实现的not in
。当我们写pattern in string
时,左操作数应该是一个字符串,并且成员资格测试检查是否string
包含pattern
作为子字符串。
如果成员资格测试返回True
,这意味着存在一个string
起始位置,您可以从该位置读取字符串中的模式。
print("apple" in "pineapple") # True
print("milk" in "yogurt") # False
有趣的是,空字符串被认为是任何字符串的子字符串。
print('' in '') # True
print('' not in "lemon") # False
字符串中的布尔搜索
除了知道子字符串只出现在字符串中之外,我们还可以确定字符串以特定模式开始或结束。startswith()
和 endswith()
方法
email = "email_address@something.com"
print(email.startswith("www.")) # False
print(email.endswith("@something.com")) # True
可选值start
和end
可添加绑定的搜索区域:string.startswith(pattern, start, end)
。当我们只指定一个附加元素时,它会自动被视为start
.
email = "my_email@something.com"
print(email.startswith("email", 2)) # False
print(email.startswith("email", 3)) # True
在上面的示例中,当我们将start
参数指定为2时,我们将搜索限制为子字符串"_email@something.com"
,它实际上不是以 开头"email"
。然后我们通过将 start 设置为3来修复这个错误。
请注意,由开始索引和结束索引绑定的子字符串确实包括具有开始索引的字符,但不包括具有结束索引的元素。
email = "my_email@something.com"
print(email.endswith("@", 5, 8)) # False
print(email.endswith("@", 5, 9)) # True
在第一种情况下为搜索定义的子字符串是"ail"
,而在第二种情况下是"ail@"
。
元素位置
现在,我们知道如何检查字符串是否包含子字符串、以它开头或结尾,让我们学习如何定义子字符串的确切位置。我们可以使用方法find()
或index()
这样做:
best = "friend"
print(best.find("i")) # 2
print(best.index("i")) # 2
它们的工作原理完全相同,只是前者-1
在找不到给定元素时返回,而后者则 raise ValueError
。
print(best.find("u")) # -1
print(best.index("u")) # ValueError
因此,find()
下面的所有示例也可以使用index()
。
我们既可以搜索单个字符,也可以搜索更长的子字符串。在后一种情况下,返回子字符串的第一个字符的索引。
print(best.find("end")) # 3
在字符串friend
中,子字符串end
占据3到5的位置,并返回起始索引。请记住,这两种方法都只返回我们搜索的元素第一次出现的索引。
magic = "abracadabra"
print(magic.find("ra")) # 2
但是,我们可以另外指定搜索的间隔,就像布尔搜索一样:string.find(pattern, start, end)
。
print(magic.find("ra", 5)) # 9
print(magic.find("ra", 5, 10)) # -1
再一次,结束索引不包括在搜索区域中。
或者,我们可以使用方法rfind()
和rindex()
从字符串的末尾向后搜索。
print(magic.rfind("ra")) # 9
print(magic.rindex("a")) # 10
元素数量
最后,计算一个元素(字符或子字符串)在字符串中出现的次数通常很有用,为此,我们可以使用方法count()
.
magic = "abracadabra"
print(magic.count("abra")) # 2
print(magic.count("a")) # 5
概括
在本主题中,我们研究了搜索字符串的不同方面,并学习了如何定位特定模式。现在您将能够:
- 要在 Python 中实现子字符串搜索算法,
- 要测试文本中的成员资格,
- 要检查字符串是否以特定模式开始或结束,
- 要找到子字符串的确切位置,
- 计算一个模式在文本中出现的次数。