【问题标题】:Remove duplicate words from text file input?从文本文件输入中删除重复的单词?
【发布时间】:2014-05-08 10:46:35
【问题描述】:

我正在玩一个需要 3 个参数的函数,一个文本文件的名称,substring1 和 substring2。它将搜索文本文件并返回包含两个子字符串的单词:

def myfunction(filename, substring1, substring2)
    result = ""
    text=open(filename).read().split()
    for word in text:
        if substring1 in word and substring2 in word:
            result+=word+" "
    return result

此功能有效,但我想删除重复的结果。例如,对于我的特定文本文件,如果 substring1 是“at”并且 substring2 是“wh”,它将返回“what”,但是,因为我的文本文件中有 3 个“what”,它会返回所有这些。我正在寻找一种不返回重复项的方法,只返回唯一的单词,我还想保留 ORDER,所以这算不算“集合”?

我想也许对“文本”做一些事情会起作用,以某种方式在循环之前删除重复项。

【问题讨论】:

  • 一个集合不会保留顺序,但是

标签: python function for-loop text-files


【解决方案1】:

这是一个使用 小内存(在文件行上使用迭代器)并且具有 良好的时间复杂度(这在返回的单词列表时很重要)的解决方案很大,比如substring1 是“a”,substring2 是“e”,英语):

import collections

def find_words(file_path, substring1, substring2)
    """Return a string with the words from the given file that contain both substrings."""
    matching_words = collections.OrderedDict()
    with open(file_path) as text_file:
        for line in text_file:
            for word in line.split():
                if substring1 in word and substring2 in word:
                    matching_words[word] = True
    return " ".join(matching_words)

OrderedDict 保留了第一次使用键的顺序,因此这使单词保持找到它们的顺序。由于是映射,所以没有重复的单词。由于在 OrderedDict 中插入密钥是在恒定时间内完成的(与许多其他解决方案的 if word in result_list 的线性时间相反),因此获得了良好的时间复杂度。

【讨论】:

    【解决方案2】:

    不,您需要做的就是将result 设为列表而不是字符串。然后,在添加每个单词之前,您可以执行if word not in result:。您可以稍后通过''.join(result) 将列表转换为以空格分隔的字符串。

    这将保留它们被发现的顺序,而集合则不会。

    【讨论】:

    • 哦,好吧,我试试看,我之前确实尝试过使用 result 作为字符串而不使用“if word not in result”,并且列表最终是正确的单词,但是它们是用逗号逐个字母分隔?
    • @user3528330 听起来您使用的是extend 而不是append
    【解决方案3】:

    如果您想保持订单,我认为最好的方法是创建results 一个列表,并在添加之前检查每个word 是否已经在列表中。另外,你真的应该使用上下文管理器with 来处理文件,以确保它们被正确关闭:

    def myfunction(filename, substring1, substring2)
        result = []
        with open(filename) as f:
            text = f.read().split()
        for word in text:
            if substring1 in word and substring2 in word and word not in result:
                result.append(word)
        return " ".join(result)
    

    【讨论】:

    • 与 zmo 的评论相同:这具有糟糕的时间复杂度。
    • @EOL 确实如此,但另一方面它简单易读,n 可能不是很大。
    • @jonrsharpe 这是一个有趣的观点,但是由于它的OrderedDict,Python 确实为我们提供了一个非常简单的解决方案。至于“n可能不是很大”,我们真的不知道(如果substring1是'e',substring2是'a',英文肯定不是这样)。无论如何,我认为没有太多理由不选择有效的解决方案(同样,高效 = 良好的时间复杂度):它需要完全相同的行数并且读取几乎相同。
    【解决方案4】:

    请使用 with 语句来使用文件的上下文管理器。使用列表并测试列表中是否存在字符串将为您完成这项工作:

    def myfunction(filename, substring1, substring2)
        result = []
        with open(filename) as f:
            for word in f.read().split():
                if substring1 in word and substring2 in word:
                     if not word in result:
                         result.append(word)
            return result
    

    并考虑返回一个列表而不是字符串,因为您可以随时轻松地将列表转换为字符串,这样做:

    r = myfunction(arg1, arg2, arg3)
    print(",".join(r))
    

    编辑:

    @EOL 完全正确,所以我在这里提供两种更省时的方法(但内存效率略低):

    from collections import OrderedDict
    def myfunction(filename, substring1, substring2)
        result = OrderedDict()
        with open(filename) as f:
            for word in f.read().split():
                if substring1 in word and substring2 in word:
                     result[word] = None # here we don't care about the stored value, only the key
            return result.values()
    

    OrderedDict 是一个保留插入顺序的字典。字典的键是set 的特例,它们共享只有唯一值的属性。因此,如果一个键已经在字典中,当第二次插入时,它将被静默忽略。该操作比在列表中查找值要快得多。

    【讨论】:

    • if not word in result 效率不高(就时间复杂度而言)。例如,更合适的结构是 OrderedDict,它的成员资格测试时间复杂度要好得多。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-28
    相关资源
    最近更新 更多