如何用列表推导式实现停用词过滤?原代码问题解析与解决
问题分析与解决
首先咱们先理清你代码里的核心问题:
你原来代码的隐藏bug
你最初的代码里,for word in line这一行,如果line是字符串类型的话,Python会逐个迭代字符串里的每个字符,而不是把line拆成单词。比如line = "hello world",for word in line会依次取出'h'、'e'、'l'...这就导致你后续的word.split()对单个字符来说,结果是比如['h'],和你的stopwords(应该是字符串列表)比较时,['h'] not in stopwords永远为真,最终useful_word会塞满所有字符,完全不是你想要的效果。
你列表推导尝试的问题
你写的这段代码:
for line in analysis_words: useful_word = " ".join([word for word in line.split()if word not in stopwords])
其实拆分单词的部分line.split()是对的,但有两个问题:
- 每次循环都会把
useful_word覆盖成当前line处理后的字符串,最后你只能得到最后一个line的处理结果,而不是所有line的结果集合; - 没有明确你最终想要的结果形式:是把所有非停用词收集到一个大列表,还是每个line对应一个过滤后的字符串列表?
正确的实现方式
根据你的需求,分两种情况给出方案:
情况1:收集所有非停用词到一个大列表
如果你想把所有line里的非停用词都放进一个列表(和你最初useful_word = []的目标一致),可以用嵌套列表推导一行搞定:
useful_words = [word for line in analysis_words for word in line.split() if word not in stopwords]
这等价于你最初想写的正确两层循环:
useful_words = [] for line in analysis_words: # 先把line拆成单词列表,而不是遍历字符 for word in line.split(): if word not in stopwords: useful_words.append(word)
情况2:每个line对应一个过滤后的字符串
如果你想保留每个line的结构,把每个line处理成只含非停用词的字符串,然后收集这些字符串到列表,那么可以这样写:
# 普通循环写法 useful_lines = [] for line in analysis_words: # 过滤当前line里的非停用词 filtered_words = [word for word in line.split() if word not in stopwords] # 把过滤后的单词拼成字符串,加入列表 useful_lines.append(" ".join(filtered_words)) # 或者用列表推导一行实现 useful_lines = [" ".join(word for word in line.split() if word not in stopwords) for line in analysis_words]
这里注意," ".join()里可以直接用生成器表达式word for word in ...,比列表推导更节省内存。
内容的提问来源于stack exchange,提问作者OgnjanD
相关产品推荐
相关产品推荐

