Python字符串find返回-1:lower方法引发的token定位异常及修复咨询
问题
我编写了一个函数用于接收字符串并返回各token的位置。当直接使用tokens = query_string.split()时函数运行正常,但改用query_string.lower().split()生成tokens后,调用原字符串的find方法,得到的第一个元组为(-1, 2),而非预期的(0, 3)。测试字符串为'This is a test',相关代码如下:
def token_position_list(query_string): """ :param query_string: a string representing a query :return: a list of tuples, where each tuple holds the start and end positions of each token """ token_positions = [] tokens = query_string.lower().split() current_position = 0 for token in tokens: start_position = query_string.find(token, current_position) end_position = start_position + len(token) - 1 token_positions.append((start_position, end_position)) current_position = end_position + 1 return token_positions
原因分析
核心问题是大小写不匹配导致查找失败:
- 原字符串的第一个token是
This(首字母大写),但query_string.lower().split()生成的第一个token是全小写的this。 - Python的
str.find()方法是区分大小写的,在原字符串中找不到全小写的this,因此返回-1。后续计算end_position = -1 + 4 - 1 = 2,就出现了错误的(-1, 2)元组。 - 后面的
is、a、test因为原字符串中本身就是小写,所以能正常匹配到对应位置。
修复方案
根据实际需求,有两种可行的修复方式:
方案1:不区分大小写查找token位置(适合需要忽略大小写匹配的场景)
使用正则表达式实现不区分大小写的查找,确保能匹配到原字符串中大小写不同的token:
import re def token_position_list(query_string): token_positions = [] tokens = query_string.lower().split() current_position = 0 for token in tokens: # 用正则查找不区分大小写的匹配,从当前位置开始 match = re.search(re.escape(token), query_string[current_position:], re.IGNORECASE) if match: start_position = current_position + match.start() end_position = start_position + len(token) - 1 token_positions.append((start_position, end_position)) current_position = end_position + 1 else: # 处理找不到的情况,可根据需求调整逻辑 token_positions.append((-1, -1)) return token_positions
方案2:保留原始token拆分(适合需要严格对应原字符串token的场景)
先拆分原始字符串的token,再按需转小写,直接用原始token查找位置,避免大小写不匹配问题:
def token_position_list(query_string): token_positions = [] current_position = 0 # 直接拆分原始字符串的token for token in query_string.split(): start_position = query_string.find(token, current_position) end_position = start_position + len(token) - 1 token_positions.append((start_position, end_position)) # 如果需要小写token,可在此生成 lower_token = token.lower() current_position = end_position + 1 return token_positions
两种方案测试输入'This is a test',都会返回预期的[(0, 3), (5, 6), (8, 8), (10, 13)]。
内容的提问来源于stack exchange,提问作者Helpme
相关产品推荐
相关产品推荐

