分割成句子后对齐空格

Align whitespace after segmentation into sentences

提问人:Christopher Oezbek 提问时间:1/15/2022 更新时间:1/21/2022 访问量:33

问:

我正在使用分割库将字符串拆分为句子:

s = "Lucas ipsum dolor sit amet darth\n 
     mandalore kit. Endor Mr. Wookiee wicket\n 
     jawa yavin ackbar jabba? Padmé\n
     utapau palpatine kenobi moff.\n
     Sidious anakin mace:\n
      - Ben darth.\n
      - Ben vader."

segment(s)
# => 
["Lucas ipsum dolor sit amet darth mandalore kit.",
 "Endor Mr. Wookiee wicket jawa yavin ackbar jabba?",
 "Padmé utapau palpatine kenobi moff.",
 "Sidious anakin mace:",
 "- Ben darth.",
 "- Ben vader."]

遗憾的是,库无法保留空格,而是剥离了所有换行符、前导和尾随换行符,并将多个空格折叠为一个空格。

鉴于细分库在其他方面很棒(它保留了像 Mr. Wookie 这样的东西): 鉴于原始文本仍然可用,将空格重新插入拆分句子的简洁代码是什么?

预期成果:

["Lucas ipsum dolor sit amet darth\nmandalore kit. ",
 "Endor Mr. Wookiee wicket\njawa yavin ackbar jabba? ",
 "Padmé\nutapau palpatine kenobi moff.\n",
 "Sidious anakin mace:\n",
 " - Ben darth.\n",
 " - Ben vader."]

原始代码是 Ruby,但解决方案可以使用任何语言。

与字符串 语言无关 的句子

评论


答:

1赞 Dillon Davis 1/21/2022 #1

我认为最简单、最简洁的方法(尽管肯定不是最有效的)是使用正则表达式。这个想法是转义每个分段的行,用任何空格的 1+ 的正则表达式替换空格,在每个图案的开头和结尾允许空格,将它们粘合在捕获组中,并将原始文本与之匹配。

在 python 中:

import re

def insert_whitespace(original, segmented):
    inner = "".join(r"([ \t]*{}[ \t]*(?:\s*\n)?)".format(
        re.escape(line).replace(r"\ ", r"\s+"))
        for line in segmented)
    pattern = f"^{inner}$"

    return re.match(pattern, original).groups()

例:

from pprint import pprint

original = """Lucas ipsum dolor sit amet darth\n
 mandalore kit. Endor Mr. Wookiee wicket
 jawa yavin ackbar jabba? Padmé
utapau palpatine kenobi moff.
Sidious anakin mace:
 - Ben darth.
 - Ben vader."""

segmented = ["Lucas ipsum dolor sit amet darth mandalore kit.",
 "Endor Mr. Wookiee wicket jawa yavin ackbar jabba?",
 "Padmé utapau palpatine kenobi moff.",
 "Sidious anakin mace:",
 "- Ben darth.",
 "- Ben vader."]

output = insert_whitespace(original, segmented)
pprint(output)
# out: ('Lucas ipsum dolor sit amet darth\n\n mandalore kit. ',
# out:  'Endor Mr. Wookiee wicket\n jawa yavin ackbar jabba? ',
# out:  'Padmé\nutapau palpatine kenobi moff.\n',
# out:  'Sidious anakin mace:\n',
# out:  ' - Ben darth.\n',
# out:  ' - Ben vader.')

注意: 在决定放置某些空格的位置时,您可能需要根据需要更新正则表达式(包括第一个换行符之前的所有内容都附加到前一句,或者可能是除尾随空格以外的所有空格等)。诚然,我使用的正则表达式有点粗糙,但它应该优雅地处理所有形式的空格,并且大多数时候都会明智地附加/预置。

评论

0赞 Christopher Oezbek 1/21/2022
我喜欢!我自己的“解决方案”是两个字符串的字符上的一个可怕的for循环。问题在于,行分段不仅会折叠空格,还会清理一些东西,例如将两个反引号合并为一个引号字符。
0赞 Dillon Davis 1/21/2022
@ChristopherOezbek如果你能弄清楚它的所有转换,你可以像我在 ..replace(r"\ ", r"\s+")
0赞 Dillon Davis 1/21/2022
例如,,或类似的东西.replace('"', '(?:"|``)')
0赞 Christopher Oezbek 1/21/2022
是的,有道理。如果正则表达式不匹配会怎样?它不会返回任何东西,对吧?
0赞 Dillon Davis 1/21/2022
@ChristopherOezbek它会出错。但是,理想情况下,正则表达式不可能不匹配,只要包含所有转换即可。