【问题标题】:python re.sub ignoring hyphens without removing them from the outputpython re.sub 忽略连字符而不从输出中删除它们
【发布时间】:2021-02-24 14:45:42
【问题描述】:

我想匹配写成单词的数字,并将这些单词替换为它们的等效数字。

简化示例:

我有一个 CSV 文件,其中包含:

twenty-two\t22
seventy-two thousand\t72000
etc.

在我的文本中,我可以使用或不使用连字符来书写数字。所以我要做的是匹配忽略连字符的单词,但我不想删除文本中的所有连字符(以防文本的其他地方有连字符)。

An off-campus apartment that costs seventy-two thousand dollars.
=> An off-campus apartment that costs 72000 dollars.
An off-campus apartment that costs seventy two thousand dollars.
=> An off-campus apartment that costs 72000 dollars.

我的代码:

def transform(line,file):
    
    listfile = []
    with open(file,"r") as rscf :
        read_ressource = csv.reader(rscf, delimiter="\t")
        for row in read_ressource :
            listfile.append(row)

        dictRessource =  {str(rows[0]):str(rows[1]) for rows in listfile}
    
    regex = "|".join([rf"\b{x}\b(?!((\s?\b\d\b\s?)|(\s?(hundred|thousand|mille|milliard|million|billion|trillion))?(\s?\(?\d?{y}\)?)))" for x,y in dictRessource.items()])  
    return re.sub(f'{regex}', lambda match: dictRessource[str.lower(match.group(0))], line, flags=re.IGNORECASE) 

到目前为止我尝试了什么:

def transform(line,file):
    pattern = re.compile("-")
    listfile = []
    with open(file,"r") as rscf :
        read_ressource = csv.reader(rscf, delimiter="\t")
        for row in read_ressource :
            listfile.append(row)
            
        dictRessourcesWith =  {str(rows[0]):str(rows[1]) for rows in listfile}
        dictRessourcesSans = {pattern.sub(' ',str(rows[0])):str(rows[1]) for rows in listfile}
    
    dictRessource = {**dictRessourcesWith, **dictRessourcesSans}

    
    regex = "|".join([rf"\b{x}\b(?!((\s?\b\d\b\s?)|(\s?(hundred|thousand|mille|milliard|million|billion|trillion))?(\s?\(?\d?{y}\)?)))" for x,y in dictRessource.items()])  
    return re.sub(f'{regex}', lambda match: dictRessource[str.lower(match.group(0))], line, flags=re.IGNORECASE) 

但是因为我正在处理非常大的文本文件,所以我正在寻找一种方法来做到这一点,即从一开始就直接忽略连字符,而不必创建更大的正则表达式,从而使处理过程花费更长的时间。

谢谢

【问题讨论】:

  • 看来您需要将-替换为[-\s],即在regex变量中将{x}替换为{x.replace('-', r'[-\s]')},并将{y}替换为{y.replace('-', r'[-\s]')}
  • 我试过了,但它不起作用。 “x”和“y”是我的字典的键/值(单词/数字)。不知道为什么我需要替换 {y} 中的“-”。
  • 对,不用y,对不起。但它应该适用于x。您只需要在搜索正确的值时确保键是正确的,match.group().replace(" ", "") 或类似的东西,而不是 str.lower(match.group(0))
  • 我不知道我做错了什么,但这仍然不适合我。如果我执行 dict[match.group(0).replace("-", " ")] 或 , dict[match.group(0)].replace("-", " ") 我得到一个关键错误键是一个词,如“一”或“二”。如果我这样做了 (adict[match.group(0)]).replace("-", ""),它就不起作用了。

标签: python-3.x regex substitution


【解决方案1】:

您的正则表达式数据带有连字符,您的文本可以带有 either - 或数字部分之间的空格。这意味着,您需要将文本与 [- ][-\s] 模式匹配,而不仅仅是连字符。

在构建字典时,您可以继续使用带有连字符的小写rows[1]数据,但在匹配时,您需要将-替换为[- ]/[-\s]

sample code snippet 可能看起来像

import re

file_text = 'twenty-two\t22\nseventy-two thousand\t72000'
listfile = [x.split('\t') for x in file_text.splitlines()]
dictRessource = {str(rows[0]):str(rows[1]) for rows in listfile}
regex = re.compile( "|".join([r"\b{}\b(?!((\s?\b\d\b\s?)|(\s?(hundred|thousand|mille|milliard|million|billion|trillion))?(\s?\(?\d?{}\)?)))".format(x.replace('-', r'[\s-]'), y) for x,y in dictRessource.items()]) , re.I)
    
def transform(line):
    return regex.sub(lambda match: dictRessource[match.group(0).lower().replace(' ', '-')], line) 
    
print( transform("Some tWenty-two things and twEnty two ...") )
# => Some 22 things and 22 ...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-13
    • 1970-01-01
    相关资源
    最近更新 更多