我有一些pascal格式的文本,我试图分割成单独的令牌/单词. 例如,"Hello123AIIsCool"会变成["Hello", "123", "AI", "Is", "Cool"].

Some Conditions

  • 单词总是以大写字母开头.例如,"Hello"
  • 一个连续的数字序列应该放在一起.例如,"123"["123"],不是["1", "2", "3"]>
  • 当最后一个字母是第一个条件中定义的新词的开始时,大写字母的连续序列应该保持在一起except.例如,"ABCat"["AB", "Cat"],不是["ABC", "at"]>
  • 不能保证每个条件在字符串中都有匹配项.例如,"Hello""HelloAI""HelloAIIsCool""Hello123""123AI""AIIsCool"以及我没有提供的任何其他组合都是潜在的候选者.

我试过几种正则表达式的变体.接下来的两次try 让我非常接近我想要的,但并不完全.

Version 0

import re

def extract_v0(string: str) -> list[str]:
    word_pattern = r"[A-Z][a-z]*"
    num_pattern = r"\d+"
    pattern = f"{word_pattern}|{num_pattern}"
    extracts: list[str] = re.findall(
        pattern=pattern, string=string
    )
    return extracts

string = "Hello123AIIsCool"
extract_v0(string)
['Hello', '123', 'A', 'I', 'Is', 'Cool']

Version 1

import re

def extract_v1(string: str) -> list[str]:
    word_pattern = r"[A-Z][a-z]+"
    num_pattern = r"\d+"
    upper_pattern = r"[A-Z][^a-z]*"
    pattern = f"{word_pattern}|{num_pattern}|{upper_pattern}"
    extracts: list[str] = re.findall(
        pattern=pattern, string=string
    )
    return extracts

string = "Hello123AIIsCool"
extract_v1(string)
['Hello', '123', 'AII', 'Cool']

Best Option So Far

这使用了regex和循环的组合.这是可行的,但这是最好的解决方案吗?或者有什么奇特的正则表达式可以做到这一点?

import re

def extract_v2(string: str) -> list[str]:
    word_pattern = r"[A-Z][a-z]+"
    num_pattern = r"\d+"
    upper_pattern = r"[A-Z][A-Z]*"
    groups = []
    for pattern in [word_pattern, num_pattern, upper_pattern]:
        while string.strip():
            group = re.search(pattern=pattern, string=string)
            if group is not None:
                groups.append(group)
                string = string[:group.start()] + " " + string[group.end():]
            else:
                break
    
    ordered = sorted(groups, key=lambda g: g.start())
    return [grp.group() for grp in ordered]

string = "Hello123AIIsCool"
extract_v2(string)
['Hello', '123', 'AI', 'Is', 'Cool']

推荐答案

根据你的版本1:

import re


def extract_v1(string: str) -> list[str]:
    word_pattern = r"[A-Z][a-z]+"
    num_pattern = r"\d+"
    upper_pattern = r"[A-Z]+(?![a-z])"  # Fixed
    pattern = f"{word_pattern}|{num_pattern}|{upper_pattern}"
    extracts: list[str] = re.findall(
        pattern=pattern, string=string
    )
    return extracts


string = "Hello123AIIsCool"
extract_v1(string)

结果:

['Hello', '123', 'AI', 'Is', 'Cool']

固定的upper_pattern将匹配尽可能多的大写字母,并将停止一个小写字母之前,如果它存在.

Python相关问答推荐

Polars比较了两个预设-有没有方法在第一次不匹配时立即失败

Select 用a和i标签包裹的复选框?

根据在同一数据框中的查找向数据框添加值

Pytest两个具有无限循环和await命令的Deliverc函数

从numpy数组和参数创建收件箱

当我try 在django中更新模型时,模型表单数据不可见

Polars asof在下一个可用日期加入

matplotlib + python foor loop

ruamel.yaml dump:如何阻止map标量值被移动到一个新的缩进行?

BeautifulSoup:超过24个字符(从a到z)的迭代失败:降低了首次深入了解数据集的复杂性:

从一个df列提取单词,分配给另一个列

如何获得3D点的平移和旋转,给定的点已经旋转?

获取git修订版中每个文件的最后修改时间的最有效方法是什么?

有了Gekko,可以创建子模型或将模型合并在一起吗?

TypeError:';Locator';对象无法在PlayWriter中使用.first()调用

为什么我的scipy.optimize.minimize(method=";newton-cg";)函数停留在局部最大值上?

类型对象';敌人';没有属性';损害';

如何在Python中创建仅包含完整天数的月份的列表

如果列包含空值,则PANAS查询不起作用

大Pandas 中的群体交叉融合