从字符串中删除一组单词

51
我有一个停用词列表和一个搜索字符串,我想从字符串中删除这些单词。
例如:
stopwords=['what','who','is','a','at','is','he']
query='What is hello'
现在代码应该剥离'What'和'is'。但是在我的情况下,它剥离了'a'以及'at'。我已经在下面给出了我的代码。我可能做错了什么?
现在代码应该剥离'What'和'is'。但是在我的情况下,它剥离了'a'以及'at'。我已经在下面给出了我的代码。我可能做错了什么?
for word in stopwords:
    if word in query:
        print word
        query=query.replace(word,"")
如果输入查询是"What is Hello",我会得到输出:
wht s llo 为什么会这样?

如果您想进行全词匹配,应将“query”拆分为列表并进行搜索。query.split() - karthikr
好的,我会尝试! - Rohit Shinde
有没有一种使用正则表达式来完成这个的方法? - information_interchange
6个回答

81

这是一种方法:

query = 'What is hello'
stopwords = ['what', 'who', 'is', 'a', 'at', 'is', 'he']
querywords = query.split()

resultwords  = [word for word in querywords if word.lower() not in stopwords]
result = ' '.join(resultwords)

print(result)

我注意到您想要在列表中包含小写变体的情况下删除一个单词,因此我已经在条件检查中添加了对 lower() 的调用。


1
它创建一个新列表,其中包含所有小写变体未在停用词中找到的单词。 - Robby Cornelissen
2
@RohitShinde:这是一个列表推导式(list comprehension)。 - whereswalden
@RobbyCornelissen 只处理文字,但如果你有一个停用词列表,例如 ['这个怎么样', '那个呢'],并且你的查询语句是“你好,请尝试删除这个怎么样或那个呢”,它将无法正常工作。 - DevMan
@DevMan 嗯...是的,因为“这个怎么样”不是一个单词而是一个短语?我只能回答被问到的问题,那就是关于单词而非短语的。 - Robby Cornelissen
1
这在使用空格分隔词汇的语言中效果很好。但对于一些像中文这样的语言,这并不适用。 - Raptor
显示剩余2条评论

16

接受的答案适用于由空格分隔的单词列表,但在现实生活中并非如此,因为单词之间可能有标点符号。在这种情况下需要使用 re.split

此外,使用setstopwords进行测试可以加快查找速度(即使在单词数量较少时存在字符串哈希和查找之间的权衡)

我的建议:

import re

query = 'What is hello? Says Who?'
stopwords = {'what','who','is','a','at','is','he'}

resultwords  = [word for word in re.split("\W+",query) if word.lower() not in stopwords]
print(resultwords)

输出结果(作为单词列表):

['hello','Says','']

由于re.split令人讨厌地产生了空字段,因此最后有一个空字符串需要过滤掉。这里有两个解决方法:

resultwords  = [word for word in re.split("\W+",query) if word and word.lower() not in stopwords]  # filter out empty words

或者将空字符串添加到停用词列表中 :)

stopwords = {'what','who','is','a','at','is','he',''}

现在代码打印:

['hello','Says']

11

在karthikr所说的基础上,尝试一下

' '.join(filter(lambda x: x.lower() not in stopwords,  query.split()))

说明:

query.split() #splits variable query on character ' ', e.i. "What is hello" -> ["What","is","hello"]

filter(func,iterable) #takes in a function and an iterable (list/string/etc..) and
                      # filters it based on the function which will take in one item at
                      # a time and return true.false

lambda x: x.lower() not in stopwords   # anonymous function that takes in variable,
                                       # converts it to lower case, and returns true if
                                       # the word is not in the iterable stopwords


' '.join(iterable) #joins all items of the iterable (items must be strings/chars)
                   #using the string/char in front of the dot, i.e. ' ' as a joiner.
                   # i.e. ["What", "is","hello"] -> "What is hello"

我尝试了你说的。它给了我一个错误,说函数类型的参数不可迭代。 - Rohit Shinde
你能解释一下这一行代码是干什么的吗? - Rohit Shinde
你为什么要使用 listsplit(' ') - Padraic Cunningham
我最初没有使用列表,这是一个编辑,我不确定他为什么会出现错误。我认为可能是因为他的过滤器对象在旧版本中不能用作可迭代对象。split函数用于将字符串分割成单词。 - pseudonym
是的,但您不需要指定 ' ',尝试拆分'What is hello' - Padraic Cunningham

8

看到你的问题,我注意到其他回答告诉了你如何做你想做的事情,但是他们没有回答你最后提出的问题。

如果输入查询为“什么是Hello”,我的输出结果是:

wht s llo

这是为什么?

这是因为.replace()精确替换你给它的子字符串。

例如:

"My, my! Hello my friendly mystery".replace("my", "")

提供:

>>> "My, ! Hello  friendly stery"

.replace() 实质上是将字符串按照作为第一个参数给定的子字符串进行分割,并使用第二个参数将其重新合并。

"hello".replace("he", "je")

逻辑上类似于:

"je".join("hello".split("he"))

如果你还想使用.replace删除整个单词,可能会认为在前后添加空格就足够了,但这样会漏掉字符串开头和结尾的单词,以及子字符串的标点版本。
"My, my! hello my friendly mystery".replace(" my ", " ")
>>> "My, my! hello friendly mystery"

"My, my! hello my friendly mystery".replace(" my", "")
>>> "My,! hello friendlystery"

"My, my! hello my friendly mystery".replace("my ", "")
>>> "My, my! hello friendly mystery"

此外,在添加空格之前或之后是不会捕获重复项的,因为它已经处理了第一个子字符串,并会忽略它,而继续进行:

"hello my my friend".replace(" my ", " ")
>>> "hello my friend"

出于这些原因,Robby Cornelissen被采纳的答案是实现您想要的功能的推荐方法。

0
" ".join([x for x in query.split() if x not in stopwords])

-1
stopwords=['for','or','to']
p='Asking for help, clarification, or responding to other answers.'
for i in stopwords:
  n=p.replace(i,'')
  p=n
print(p)

尽管这段代码可能解决问题,但一个好的答案应该解释代码做了什么以及它如何帮助解决问题。 - BDL
这段代码将会做与问题所询问的完全相同的事情。它既没有解决问题,也没有解释为什么它不能做到他们想要的。 - B.Adler

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