Python使用正则表达式将文本拆分为令牌

时间:2019-02-17 14:24:07

标签: python regex

嗨,我有一个关于将字符串拆分为标记的问题。

这是一个示例字符串:

  

string =“当我在等待时,一个人从一间侧室出来,一眼就能确定他一定是长约翰。他的左腿被臀部割断,在下面他的左肩carried着拐杖,非常灵巧地管理着它,像只鸟一样在它上面跳来跳去。他高大而强壮,脸像火腿一样大,脸色苍白,苍白,但聪明而微笑。他似乎洋溢着最开朗的精神,在桌子间四处走动时吹口哨,用快乐的话语或一巴掌打招呼,以迎接客人的青睐。”

,并且我正在尝试将string正确地分成其令牌。

这是我的功能count_words

def count_words(text):
    """Count how many times each unique word occurs in text."""
    counts = dict()  # dictionary of { <word>: <count> } pairs to return
    #counts["I"] = 1
    print(text)
    # TODO: Convert to lowercase
    lowerText = text.lower()
    # TODO: Split text into tokens (words), leaving out punctuation
    # (Hint: Use regex to split on non-alphanumeric characters)
    split = re.split("[\s.,!?:;'\"-]+",lowerText)
    print(split)
    # TODO: Aggregate word counts using a dictionary

split的结果

  

['as','i','was','waiting','a','man','came','out','of','a',   “侧面”,“房间”,“和”,“在”,“一个”,“扫视”,“我”,“是”,“确定”,“他”,   “必须”,“是”,“长”,“约翰”,“他”,“左”,“腿”,“是”,“切”,   “关闭”,“关闭”,“通过”,“该”,“臀部”,“和”,“下方”,“该”,“左侧”,   “肩膀”,“他”,“携带”,“一个”,“拐杖”,“其中”,“他”,“受管理”,   “有”,“精彩”,“灵巧”,“跳跃”,“关于”,“在”,“它”,   “喜欢”,“一只”,“鸟”,“他”,“是”,“非常”,“高”,“和”,“强壮”,   “ with”,“ a”,“ face”,“ as”,“ big”,“ as”,“ a”,“ ham-plain”,“ and”,   “苍白”,“但是”,“智能”,“和”,“微笑”,“确实”,“他”,   “似乎”,“中”,“该”,“最”,“开朗”,“精神”,“低语”,   “是”,“他”,“移动”,“大约”,“中间”,“该”,“桌子”,“带有”,“一个”,   “快乐”,“单词”,“或”,“一个”,“巴掌”,“上”,“该”,“肩膀”,“用于”,   'the','more','favoured','of','his','guests','']

如您所见,''列表的最后一个索引中有一个空字符串split

请帮助我理解列表中的空字符串,并正确分割此示例string

5 个答案:

答案 0 :(得分:3)

您可以使用list comprehension遍历re.split产生的列表项,并仅在它们不是空字符串时保留它们:

def count_words(text):
    """Count how many times each unique word occurs in text."""
    counts = dict()  # dictionary of { <word>: <count> } pairs to return
    #counts["I"] = 1
    print(text)
    # TODO: Convert to lowercase
    lowerText = text.lower()
    # TODO: Split text into tokens (words), leaving out punctuation 
    # (Hint: Use regex to split on non-alphanumeric characters) 

    split = re.split("[\s.,!?:;'\"-]+",lowerText)
    split = [x for x in split if x != '']  # <- list comprehension
    print(split) 

您还应该考虑从函数返回数据,并从调用方打印数据,而不是从函数内部打印数据。这将为您将来提供灵活性。

答案 1 :(得分:2)

发生这种情况是因为字符串的末尾是.,并且它在拆分pattern中,所以,当匹配.时,下一个匹配将以空开头,这就是为什么看到{ {1}}。

我建议使用''这种解决方案,而不是像这样使用相反的方式:

re.findall

答案 2 :(得分:1)

Python的wiki解释了此行为:

  

如果分隔符中有捕获组,并且在   字符串开头,结果将以空字符串开头。的   字符串的末尾也是如此

即使您实际上不是捕获组,其效果也相同。请注意,它可以在结尾也可以在开头(例如,如果您的字符串以空格开头)。

其他人已经(或多或少)提出的2个解决方案是这些:

解决方案1:findall

正如其他用户指出的那样,您可以使用findall并尝试逆转模式的逻辑。对于您的角色,您可以轻松取消自己的角色类别:[^\s\.,!?:;'\"-]+

但这取决于您的正则表达式模式,因为它并不总是那么容易。

解决方案2:检查开始令牌和结束令牌

您不必检查每个标记是否为!= '',而只需查看标记中的第一个或最后一个标记,因为您急切地使用了集合中的所有字符您需要继续前进。

split = re.split("[\s\.,!?:;'\"-]+",lowerText)

if split[0] == '':
    split = split[1:]

if split[-1] == '':
    split = split[:-1]

答案 3 :(得分:1)

您有一个空字符串,这是因为一个点也匹配要在string结尾处拆分,并且任何内容都在下游。但是,您可以使用filter函数过滤掉空字符串,从而完成函数:

import re
import collections


def count_words(text):
    """Count how many times each unique word occurs in text."""

    lowerText = text.lower()

    split = re.split("[ .,!?:;'\"\-]+",lowerText)
    ## filer out empty strings and count
    ## words:

   return collections.Counter( filter(None, split) )


count_words(text=string)
# Counter({'a': 9, 'he': 6, 'the': 6, 'and': 5, 'as': 4, 'was': 4, 'with': 3, 'his': 2, 'about': 2, 'i': 2, 'of': 2, 'shoulder': 2, 'left': 2, 'dexterity': 1, 'seemed': 1, 'managed': 1, 'among': 1, 'indeed': 1, 'favoured': 1, 'moved': 1, 'it': 1, 'slap': 1, 'cheerful': 1, 'at': 1, 'in': 1, 'close': 1, 'glance': 1, 'face': 1, 'pale': 1, 'smiling': 1, 'out': 1, 'tables': 1, 'cut': 1, 'ham': 1, 'for': 1, 'long': 1, 'intelligent': 1, 'waiting': 1, 'wonderful': 1, 'which': 1, 'under': 1, 'must': 1, 'bird': 1, 'guests': 1, 'more': 1, 'hip': 1, 'be': 1, 'sure': 1, 'leg': 1, 'very': 1, 'big': 1, 'spirits': 1, 'upon': 1, 'but': 1, 'like': 1, 'most': 1, 'carried': 1, 'whistling': 1, 'merry': 1, 'tall': 1, 'word': 1, 'strong': 1, 'by': 1, 'on': 1, 'john': 1, 'off': 1, 'room': 1, 'hopping': 1, 'or': 1, 'crutch': 1, 'man': 1, 'plain': 1, 'side': 1, 'came': 1})

答案 4 :(得分:0)

import string

def count_words(text):

    counts = dict() 

    text = text.translate(text.maketrans('', '', string.punctuation))
    text = text.lower()

    words = text.split()
    print(words)

    for word in words:
        if word not in counts:
            counts[word] = 1
        else:
            counts[word] += 1

    return counts

有效。