如何找到输入列表的匹配模式,然后使用 python 用正确的模式转换替换找到的模式
Posted
技术标签:
【中文标题】如何找到输入列表的匹配模式,然后使用 python 用正确的模式转换替换找到的模式【英文标题】:how to find the matching pattern for an input list and then replace the found pattern with the proper pattern conversion using python 【发布时间】:2020-12-10 14:31:00 【问题描述】:请注意,此模式的最后两个数字(例如 FBXASC048)被指定为数字 (0-9) 的 ascii 代码
输入示例列表 ['FBXASC048009Car', 'FBXASC053002Toy', 'FBXASC050004Human'] 结果示例 ['1009Car', '5002Toy', '2004Human']
在输入列表中搜索任何这些模式的正确方法是什么
num_ascii = ['FBXASC048', 'FBXASC049', 'FBXASC050', 'FBXASC051', 'FBXASC052', 'FBXASC053', 'FBXASC054', 'FBXASC055', 'FBXASC056', 'FBXASC057']
然后将找到的模式替换为转换列表中的一项但不是随机的 因为模式列表中的每个元素只等于 conv_list 中的一个元素
conv_list = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
这是考虑到的解决方案: 它有两个部分
第一部分--> 是查找 ascii 模式[48, 49, 50, 51, 52, 53, 54, 55, 56,57] 然后用正确的十进制匹配(0-9)替换那些 所以我们将得到新的输入列表,将被称为 input_modi_list,其中 ascii 替换为十进制 第二部分->另一个使用固定模式替换使用替换功能的过程,即“FBXASC0” 新列表3
for x in input_modi_list:
y = x.replace('FBXASC0', '')
new_list3.append(new_string)
所以 new_list3 将具有上述两部分的组合结果。
我不知道是否会有一个简单的解决方案或更好的解决方案,也许使用正则表达式 另请注意,我不知道如何用十进制替换 ascii 以获取项目列表
【问题讨论】:
我相信你的问题有误:'FBXASC048009Car'应该转换成'0009Car',而不是'1009Car',因为48是0的ASCII码,而不是1。 正确,刚刚注意到哈哈哈 【参考方案1】:我认为这应该可以解决问题:
import re
input_list = ['FBXASC048009Car', 'FBXASC053002Toy', 'FBXASC050004Human']
pattern = re.compile('FBXASC(\d3,3)')
def decode(match):
return chr(int(match.group(1)))
result = [re.sub(pattern, decode, item) for item in input_list]
print(result)
现在,有一些解释:
1- pattern
对象是一个 regular expression,它将匹配以 'FBXASC' 开头并以 3 位 (0-9) 结尾的字符串的任何部分。 (\d
表示数字,3,3 表示它应该至少出现 3 次,最多出现 3 次,即正好 3 次)。另外,\d3,3 周围的括号表示匹配的三位数字将被存储以供以后使用(在下一部分中解释)。
2- decode
函数接收 match object,使用 .group(1)
提取第一个匹配组(在我们的例子中是由 \d3,3 匹配的三个数字),然后使用 @ 987654328@ 函数将字符串解析为整数(例如,将 '048' 转换为 48),最后使用chr
函数查找具有该 ASCII 码的字符。 (例如 chr(48) 将返回 '0',而 chr(65) 将返回 'A')
3- 最后一部分将re.sub
函数应用于列表的所有元素,它将用相应的 ASCII 字符替换您描述的模式 (FBXASC048[3-digits]) 的每次出现。
您可以看到,此解决方案不仅限于您的具体示例。任何数字都可以使用,只要它具有chr
函数识别的对应ASCII 字符即可。
但是,如果您确实想将其限制在 48-57 范围内,您可以简单地修改 decode
函数:
def decode(match):
ascii_code = int(match.group(1))
if ascii_code >= 48 and ascii_code <= 57:
return chr(ascii_code)
else:
return match.group(0) # returns the entire string - no modification
【讨论】:
你的解决方案是好的 9/10,但它有一个问题,它打破了只有模式列表中的内容应该被转换的规则,而其他高于或低于的 ascii 数字必须被忽略我们如何限制它所以它需要 48 到 57 之间的 ascii 数字?这就是你所说的限制的关键是非常重要的情况,如果我们可以将考虑的 ascii 数字限制在 48 到 57 之间,这将是最终的解决方案,尽管非常感谢您花时间尝试解决非常感谢您的问题 @RedBeard 我编辑了我的代码以包含您只希望更改 48-57 范围的情况。它不会触及该范围之外的任何东西。 (看答案底部)【参考方案2】:这就是我的做法。
-
只需将字符串与
|
连接即可创建正则表达式模式:
>>> num_ascii = ['FBXASC048', 'FBXASC049', 'FBXASC050', 'FBXASC051', 'FBXASC052', 'FBXASC053', 'FBXASC054', 'FBXASC055', 'FBXASC056', 'FBXASC057']
>>> conv_list = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
>>> regex_pattern = '|'.join(num_ascii)
>>> regex_pattern
'FBXASC048|FBXASC049|FBXASC050|FBXASC051|FBXASC052|FBXASC053|FBXASC054|FBXASC055
|FBXASC056|FBXASC057'
-
只需压缩两个列表即可制作查找字典:
>>> conv_table = dict(zip(num_ascii, conv_list))
>>> conv_table
'FBXASC048': '0', 'FBXASC049': '1', 'FBXASC050': '2', 'FBXASC051': '3', 'FBXASC
052': '4', 'FBXASC053': '5', 'FBXASC054': '6', 'FBXASC055': '7', 'FBXASC056': '8
', 'FBXASC057': '9'
-
遍历数据并将匹配的字符串替换为对应的数字:
>>> import re
>>> result = []
>>> for item in ['FBXASC048009Car', 'FBXASC053002Toy', 'FBXASC050004Human']:
... m = re.match(regex_pattern, item)
... matched_string = m[0]
... digit = (conv_table[matched_string])
... print(f'replacing matched_string with digit')
... result.append(item.replace(matched_string, digit))
...
replacing FBXASC048 with 0
replacing FBXASC053 with 5
replacing FBXASC050 with 2
>>> result
['0009Car', '5002Toy', '2004Human']
【讨论】:
请注意,这是一种适用于示例数据的快速简单的解决方案,但如果其中一项与正则表达式模式不匹配,则会引发错误。 您的解决方案听起来像是解决了问题不要担心输入模式将始终与提供的模式相似但是有一个问题我在当前的 python 版本上尝试过它并且它可以工作但在以前的版本 2.7.11 它不起作用我认为这一行 >> '_sre.SRE_Match' object has no attribute 'getitem' 的 TypeError这与 re.match() 函数有关,如果您有任何想法,我们如何解决这个问题@myrmica 非常感谢您尝试解决问题,非常感谢 是的,此功能是在 Python 3.6 (docs) 中添加的。在旧版本中,使用m.group(0)
作为 m[0]
的等效项。以上是关于如何找到输入列表的匹配模式,然后使用 python 用正确的模式转换替换找到的模式的主要内容,如果未能解决你的问题,请参考以下文章