【问题标题】:How to split a sentence string into words, but also make punctuation a separate element如何将一个句子字符串拆分成单词,还要让标点符号成为一个单独的元素
【发布时间】:2019-12-07 10:17:17
【问题描述】:

我目前正在尝试使用 Python 标记一些语言数据,并且很好奇是否有一种有效或内置的方法可以将句子字符串拆分为单独的单词和单独的标点符号。例如:

'Hello, my name is John. What's your name?'

如果我在这句话上使用split(),那么我会得到

['Hello,', 'my', 'name', 'is', 'John.', "What's", 'your', 'name?']

我想得到的是:

['Hello', ',', 'my', 'name', 'is', 'John', '.', "What's", 'your', 'name', '?']

我尝试使用诸如搜索字符串、查找标点符号、存储它们的索引、从字符串中删除它们然后拆分字符串以及相应地插入标点符号等方法,但是这种方法似乎效率太低,尤其是在处理大数据时语料库。

有人知道是否有更有效的方法吗?

谢谢。

【问题讨论】:

    标签: python nlp token


    【解决方案1】:

    你可以做一个技巧:

    text = "Hello, my name is John. What's your name?"
    text = text.replace(",", " , ") # Add an space before and after the comma
    text = text.replace(".", " . ") # Add an space before and after the point
    text = text.replace("  ", " ") # Remove possible double spaces
    mListtext.split(" ") # Generates your list
    

    或者只是这个输入:

    mList = input().replace(",", " , ").replace(".", " . ")replace("  ", " ").split(" ")
    

    【讨论】:

    • 刚刚忘记全部替换“?” !希望你理解我的逻辑并做到这一点
    【解决方案2】:

    这是一种使用re.finditer 的方法,它至少似乎适用于您提供的示例数据:

    inp = "Hello, my name is John. What's your name?"
    parts = []
    for match in re.finditer(r'[^.,?!\s]+|[.,?!]', inp):
        parts.append(match.group())
    
    print(parts)
    

    输出:

    ['Hello', ',', 'my', 'name', 'is', 'John', '.', "What's", 'your', 'name', '?']
    

    这里的想法是匹配以下两种模式之一:

    [^.,?!\s]+    which matches any non punctuation, non whitespace character
    [.,?!]        which matches a single punctuation character
    

    大概任何不是空格或标点符号的东西都应该是句子中的匹配词/术语。

    请注意,解决此问题的真正好方法是尝试对标点符号或空格进行正则表达式拆分。但是,re.split 不支持在零宽度外观上进行拆分,因此我们不得不尝试使用re.finditer

    【讨论】:

      【解决方案3】:

      单词标记化并不像听起来那么简单。以前使用正则表达式或字符串替换的答案并不总是处理诸如首字母缩写词或缩写之类的东西(例如a.m.、p.m.N.Y.D.I.YA.D.B.C.、@987654331 @、etc.i.e.Mr.Ms.Dr.)。除非您编写更复杂的模式来处理此类情况(但总会有烦人的异常),否则这些方法将通过此类方法拆分为单独的标记(例如B.C.)。您还必须决定如何处理其他标点符号,例如 "'$%,例如电子邮件地址和 URL、数字序列(例如 5,000.9933.3%) , 连字符(例如pre-processing, avant-garde),包含标点符号的名称(例如O'Neill),缩写(例如aren'tcan'tlet's),英语所有格标记('s)等等等等等等。

      我建议使用 NLP 库来执行此操作,因为它们应该被设置为为您处理大部分这些问题(尽管它们仍然会犯“错误”,您可以尝试修复)。见:

      前三个是完整的工具包,除了标记化之外还具有许多功能。最后一个是词性标记器,用于标记文本。这些只是其中的几个,还有其他选择,所以尝试一些,看看哪个最适合你。他们都会以不同的方式标记您的文本,但在大多数情况下(不确定 TreeTagger),您可以修改他们的标记决定以纠正错误。

      【讨论】:

        【解决方案4】:

        您可以使用re.sub 来替换string.punctuation 中定义的所有字符,后跟一个空格,在它们之前使用一个空格,最后可以使用str.split 来拆分单词

        >>> s = "Hello, my name is John. What's your name?"
        >>> 
        >>> import string, re
        >>> re.sub(fr'([{string.punctuation}])\B', r' \1', s).split()
        ['Hello', ',', 'my', 'name', 'is', 'John', '.', "What's", 'your', 'name', '?']
        

        在python2中

        >>> re.sub(r'([%s])\B' % string.punctuation, r' \1', s).split()
        ['Hello', ',', 'my', 'name', 'is', 'John', '.', "What's", 'your', 'name', '?']
        

        【讨论】:

          【解决方案5】:

          来自 nltk 的 TweetTokenizer 也可以用于此..

          from nltk.tokenize import TweetTokenizer
          
          tokenizer = TweetTokenizer()
          tokenizer.tokenize('''Hello, my name is John. What's your name?''')
          
          #op
          ['Hello', ',', 'my', 'name', 'is', 'John', '.', "What's", 'your', 'name', '?']
          

          【讨论】:

            猜你喜欢
            • 2013-04-14
            • 2010-09-26
            • 1970-01-01
            • 2019-11-07
            • 2020-06-18
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多