我正在尝试将存储在数组中的以下句子分成几类。这些类别是线号、车站、关闭类型和日期,因为我抓取的所有地铁关闭公告都是这种格式。
"Line 1: Finch to Sheppard-Yonge nightly early closures March 23 to 26 - CANCELLED"
"Line 1: Lawrence to St Clair weekend closure Sunday, March 29 - REVISED"
"Line 1: Sheppard-Yonge to St Clair nightly early closures March 30 to April 2 - REVISED"9例如:
Line = {0:"Line 1", 1:"Line 1", 2:"Line 1"}
Stations = {0: "Finch to Sheppard-Yonge", 1:"Lawrence to St Clair", 2:"Sheppard-Yonge to St Clair"}我已经创建了一些非常复杂的for循环来做这件事,然而,它们有相当多的buggy,并且对于每个类别需要不同的代码逻辑。下面是我如何从上面的句子中提取“闭包类型”的示例,我假设有3种闭包类型存储在closure_types数组中:
closure_types = ["nightly early closures","single day closure","weekend closure"]
closure_types_split = []
for closure_type in closure_types:
    split_closure_type_a = closure_type.split()
    closure_types_split.append(split_closure_type_a)
closure_type_categorized = []
for i in range(len(split_closures)): 
    for ins in range(len(closure_types_split)):
        try:
            first_word_in_closure_types_split = closure_types_split[ins][0]
            first_word = split_closures[i].index(str(first_word_in_closure_types_split))
            if split_closures[i][first_word] == 'nightly':
                last_word = first_word + 3
                closure_type_categorized.append(split_closures[i][first_word:last_word])
            elif split_closures[i][first_word] == 'single':
                last_word = first_word + 2
                closure_type_categorized.append(split_closures[i][first_word:last_word])
            elif split_closures[i][first_word] == 'weekend':
                last_word = first_word + 2
                closure_type_categorized.append(split_closures[i][first_word:last_word])
        except:
            pass我的问题是,有没有更简单的方法来做我想做的事情?或者有没有什么python库被设计用来做我想做的事情?
发布于 2020-03-26 04:45:24
这可以使用正则表达式来处理
import re
# note: spaces in the names must use `\s` (see St Clair), 
# because the re pattern uses verbose mode.
stations = '|'.join(line.strip() for line in 
    r"""
    Finch
    Lawrence
    Sheppard-Yonge
    St\sClair
    """.strip().splitlines())
# The re pattern is a raw f-string so the {stations} can be inserted.
pattern = rf"""(?ix)
    Line\s+(?P<line>\d+):
    \s*
    (?P<where>(?:{stations})(?:\s*to\s*(?:{stations}))*)    # one or more stations separated by 'to'
    \s*
    (?P<what>(?:\w*\s+)*?closures?)                         # phrase ending with closure or closures
    \s*
    (?P<when>[^-]*)                                         # everything up to a '-'
    \s*
    (?:-\s* (?P<note>.*))?                                  # if there is a '-' everything after it
    """
template = re.compile(pattern)在测试用例上使用它:
testcases = [
    "Line 1: Finch to Sheppard-Yonge nightly early closures March 23 to 26 - CANCELLED",
    "Line 1: Lawrence to St Clair weekend closure Sunday, March 29 - REVISED",
    "Line 1: Sheppard-Yonge to St Clair nightly early closures March 30 to April 2 - REVISED",
]
for test in testcases:
    mo = template.search(test)
    print(mo.groupdict())打印:
{'line': '1', 'where': 'Finch to Sheppard-Yonge', 'what': 'nightly early closures', 'when': 'March 23 to 26 ', 'note': 'CANCELLED'}
{'line': '1', 'where': 'Lawrence to St Clair', 'what': 'weekend closure', 'when': 'Sunday, March 29 ', 'note': 'REVISED'}
{'line': '1', 'where': 'Sheppard-Yonge to St Clair', 'what': 'nightly early closures', 'when': 'March 30 to April 2 ', 'note': 'REVISED'}对于更复杂的解析问题,我喜欢TatSu库。
发布于 2020-03-25 11:41:38
你的语法看起来很简单。例如:“1号线:芬奇至谢泼德-永吉夜间提前关闭3月23日至26日-取消”“1号线:劳伦斯至圣克莱尔周末关闭,3月29日星期日-修订”1号线:谢泼德至永吉至圣克莱尔3月30日至4月2日夜间提前关闭-修订
NOTICE => LINE_FIELD STATIONS CLOSURE DATES "-" STATUS
LINE_FIELD => "Line " integer ":"
STATIONS => string {"to" string}
CLOSURE => string ["closure" | "closures"] string
DATES => DATE_1 {to DATE_2}
DATE_1 => month integer
DATE_2 => {month} integer
STATUS => ["CANCELLED" | "REVISED"]我把语法交给你做了。在顶层的关键解析点是找到“闭合”字来提取闭合短语,并找到连字符来分隔最后的短语。
这能让你行动起来吗?
https://stackoverflow.com/questions/60841406
复制相似问题