从字符串中提取单词,去除标点符号并返回一个以单词为元素的列表。

20
我想知道如何实现一个函数get_words(),该函数返回一个列表,其中包含字符串中的单词,并去除标点符号。
我希望它的实现方法是用空字符串替换非string.ascii_letters字符,然后返回一个.split()
def get_words(text):

    '''The function should take one argument which is a string'''

    returns text.split()
例如:
>>>get_words('Hello world, my name is...James!')

返回:

>>>['Hello', 'world', 'my', 'name', 'is', 'James']

我已经为您格式化了问题。下次请使用“代码”按钮({})。 - johnsyweb
3个回答

40

这与拆分和标点符号无关,您只关心字母(和数字),想要一个正则表达式:

import re
def getWords(text):
    return re.compile('\w+').findall(text)

演示:

>>> re.compile('\w+').findall('Hello world, my name is...James the 2nd!')
['Hello', 'world', 'my', 'name', 'is', 'James', 'the', '2nd']
如果你不关心数字,可以将\w替换为只包含字母的[A-Za-z],或者包括缩写词在内的[A-Za-z']。可能有更高级的方法来包括带重音符号的字母-非数字字符类等其他正则表达式。

这个问题的答案我差点在这里回答:Split Strings with Multiple Delimiters?。但是你的问题实际上没有具体说明:你希望'this is: an example'被分成哪些部分:['this', 'is', 'an', 'example']还是['this', 'is', 'an', '', 'example']?我假设这是第一种情况。

引用一个提问者的话:“[this', 'is', 'an', example']是我想要的结果。是否存在一种不需要导入正则表达式的方法?如果我们只需将非ascii_letters替换为'',那么将字符串拆分为单词列表,这种方式可行吗?” 最优雅的方法是使用正则表达式,但是可以按以下方式进行处理:
def getWords(text):
    """
        Returns a list of words, where a word is defined as a
        maximally connected substring of uppercase or lowercase
        alphabetic letters, as defined by "a".isalpha()

        >>> get_words('Hello world, my name is... Élise!')  # works in python3
        ['Hello', 'world', 'my', 'name', 'is', 'Élise']
    """
    return ''.join((c if c.isalnum() else ' ') for c in text).split()

或者.isalpha()


顺便提一下:你也可以这样做,但需要导入另一个标准库:

from itertools import *

# groupby is generally always overkill and makes for unreadable code
# ... but is fun

def getWords(text):
    return [
        ''.join(chars)
            for isWord,chars in 
            groupby(' My name, is test!', lambda c:c.isalnum()) 
            if isWord
    ]
如果这是作业的话,他们可能在寻找一种命令式的方法,比如一个两状态有限状态机,其中状态为“上一个字符是否是字母”,如果从字母状态切换到非字母状态,则输出一个单词。不要这样做;这不是一个好的编程方式(尽管有时这种抽象是有用的)。

“[this', 'is', 'an', example'] is what i want. is there a method without importing regex? If we can just replace the non ascii_letters with '', then splitting the string into words in a list, would that work?” - James Smith
我正在处理一个演讲数据集,其中包含缩略词,例如 we'rethey're,使用您的正则表达式也会将带有 ' 字符的单词拆分开来。 - user7851115
1
@Peri461:你需要将正则表达式改为包含[\w']而不是\w,即“一个单词是一个或多个字母或撇号”,而不是“一个单词是一个或多个字母”。 - ninjagecko

11

尝试使用re

>>> [w for w in re.split('\W', 'Hello world, my name is...James!') if w]
['Hello', 'world', 'my', 'name', 'is', 'James']

虽然我不确定它是否能满足你所有的使用情况。

如果你想以另一种方式解决它,你可以指定你想要结果中包含的字符:

>>> re.findall('[%s]+' % string.ascii_letters, 'Hello world, my name is...James!')
['Hello', 'world', 'my', 'name', 'is', 'James']

有没有一种使用string.ascii_letters的方法来实现它? - James Smith
6
@James 如果这是作业,请使用适当的标签标记您的问题。 - Roman Bodnarchuk
我们如何使其将某些字符视为分隔符,例如:/ - Nikhil VJ

2
你所需要的只是一个分词器。可以看一下nltk,尤其是WordPunctTokenizer。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接