【问题标题】:How can I find the longest word in a text file?如何在文本文件中找到最长的单词?
【发布时间】:2013-04-23 01:08:02
【问题描述】:

我创建了一个函数来查找文本文件中的最长单词,并在可以由 9 个字母组成的文本文件中查找最长单词。我是 python 新手,我正在创建一个类似于倒计时的游戏。

我创建了一个函数来查找文本文件中最长的单词。我现在想要的是创建 python 代码来查找可以由 9 个字母组成的最长单词。

每个字母只能使用一次。因此,从“qugteroda”开始,我应该感到愤怒,愤怒,敢于,阅读,愤怒,阅读。我正在使用 python 3.3

我的代码如下所示:

def Words():
    qfile=open('dict.txt','r')
    long=''
    for line in qfile:
    if len(line)>len(long):
        long=line
    return long

【问题讨论】:

  • 所以澄清一下,您是在问如何从字母列表中找出最长的单词?你能重复字母吗?
  • 如何使最长的单词或单词。你不能重复字母。你熟悉游戏倒计时吗?
  • 您不应该使用long 作为变量名。这也是一个内置函数的名称。
  • @omz 不正确。 OP 明确指出他们正在使用 python3。
  • @wim 哦,你是对的,谢谢。

标签: python python-3.x python-3.3


【解决方案1】:

因此,您想从字典中存在的一组字母中找到最长的排序组合。

为此,您可以使用长度等于字符串长度的itertools.combinations()。您将根据已排序的字典检查所有这些组合,如果找不到匹配项,请减少组合长度。

您还希望将整个字典加载到一个集合中以减少搜索时间。我已将一组单词加载到字典中,其中键是排序后的字符串,值是具有相同排序表示的单词列表。

类似这样的:

import itertools
from collections import defaultdict

words = defaultdict(list)
with open('/usr/share/dict/words') as qfile:
    for word in qfile:
        word = word.rstrip('\n').lower()
        words[''.join(sorted(word))].append(word)

def longest_anagram(term, words):
    search_length = len(term)
    term = sorted(term) # combinations maintains sort order
    while search_length > 0:
        for combo in itertools.combinations(term, search_length):
            search = ''.join(combo) # sort above means we dont need it here
            if search in words:
                return words[search]
        search_length -= 1
    return None

found = longest_anagram('qugteroda', words)
for w in found:
    print(w)

为了完整起见,我应该提到这种方法适用于 18 个字母或更少的搜索字符串。如果您需要从大于 18 个字母的字符串中找到最长的字谜,最好翻转算法,以便按长度将字典单词排序到列表中。然后,您将遍历所有单词并检查它们是否存在于输入搜索字符串中 - 很像 @abarnert 的答案。

【讨论】:

  • 我认为您的意思是“减少搜索时间”。 :)
  • @abarnert 我确实做到了:P ta
  • 无论如何,通过这种方式,您必须遍历所有 362880 (+181440+...) 排列,以便在哈希表中查找它们。迭代字典应该快一个数量级(考虑到字典通常是 36K 单词的数量级)。当然,随着字谜变长,情况会变得更糟。 (仍然绝对值得拥有这个答案,因为 OP 应该仔细考虑这些问题。)
  • @abarnert 如果我是为自己写这篇文章,我会创建一个字典,将已排序的字符串作为键并索引到匹配项列表中。当然,假设我一次要查找多个单词。
【解决方案2】:

您当前的代码返回文本文件中最长的行,句号。

如果您想要最长的行是某个输入字符串的字谜,则需要获取一个输入字符串,并过滤掉不是字谜的行。

由于您指定没有重复字母,因此检查两个单词是否是字谜的最简单方法是检查它们是否都具有相同的字母集。所以:

def Words(inputletters):
    inputletters = set(inputletters)
    qfile=open('dict.txt','r')
    long=''
    for line in qfile:
        if set(line.strip()) == inputletters:
            if len(line)>len(long):
                long=line
    return long

如果您不是在寻找精确匹配,而只是子集,只需将== 替换为.issubset

或者,如果“你不能重复字母”实际上是指“你必须在两个字符串中完全重复 相同的个字母才能算作字谜”,这也很简单:而不是比较 set 个字母,比较一个排序的列表 个字母:

def Words(inputletters):
    inputletters = sorted(inputletters)
    qfile=open('dict.txt','r')
    long=''
    for line in qfile:
        if sorted(line.strip()) == inputletters:
            if len(line)>len(long):
                long=line
    return long

等等。一旦您可以准确定义您要搜索的内容,这可能只是对数据结构和/或比较的微不足道的更改。

我不认为这是一个完整的程序,无论你想要什么,但它应该足以 (a) 让你指向正确的方向,或者 (b) 让你澄清问题稍微好一点。


同时,还有一些其他方面您可以改进:

首先,您应该始终关闭您打开的文件(最好使用with 语句)。

虽然我们在这里,但通常的 Python 编码标准(在 PEP 8 中编码)建议使用小写的函数名称。 long 不是一个很好的变量名称——虽然它不再是 Python 3.0 的一种类型,但它可能会使自 2.x 以来一直在使用 Python 的读者感到困惑(在这一点上,它仍然是大多数)。

更有趣的是,就像 Python 中许多简单的 for 循环一样,您的整个循环可以通过使用迭代器转换调用链来替换。结果通常更简洁、更快、更难出错,并且通常更具可读性。

所以,让我们编写另一个版本来改变这一切,并检查子集而不是完整集:

def words(inputletters):
    inputletters = set(inputletters)
    with open('dict.txt') as qfile:
        words = map(str.strip, qfile)
        letters = map(set, words)
        matching = filter(inputletters.issubset, letters)
        longest = max(matching, key=len)
        return longest

当然,您可以将其中一些调用合并在一起(或者甚至将整个链变成一个单行,但我认为这可能会推动可读性的界限),或者将它们重写为生成器表达式(组合更多很好——比较 (set(line.strip()) for line in qfile)map(set, map(str.strip, file))map(lambda line: set(line.strip()), qfile)

【讨论】:

  • 虽然 OP 确实说过“你不能重复字母”,但我认为 OP 的真正意思是“你必须尊重多样性”,即如果你只有一个“e”,你就不能拼写一个带有两个“e”的单词。这就是大多数这些游戏的工作方式,包括倒计时,OP 的referenced:“每个字母只能在选择中出现的频率使用。”
  • @wim:除非我误解了您的评论,否则这正是代码的作用,也正是 OP 所要求的,所以……到底有什么问题?
  • @DSM:我试图回答 OP 实际提出的问题,而不是试图猜测他真正想要什么。但是,是的,这是一个非常明显的猜测,还有其他各种非常可能的可能性。我编辑了答案,以显示 OP 可以轻松地将其更改为适合他实际尝试解决的任何问题。感谢您的评论。
  • @abarnert OP 没有关闭他们的文件,但这并不意味着您不必这样做!
  • 我的意思是if set(line.strip()) == inputletters: 会在mississippi 这样的行上触发,而输入字母只是set('pims'),根据我对问题的解释,这将是一个错误。我还认为复制和粘贴 OP 代码而不清理诸如 python 样式约定、悬空文件句柄等明显的东西是草率的......
【解决方案3】:
def longestWord(fileName):
    mx = 0
    op = open(fileName,'r')
    words = op.read().split()
    for i in words:
        if len(i) > mx:
            mx = len(i)
            word = i
            #return the longest word and its length
    return (mx,word)

【讨论】:

  • 请考虑在代码中添加有关您的答案的更多信息
  • 虽然您的帖子可能会回答这个问题,但它缺少一些解释性文字和文档。请编辑您的答案并提供一些答案。
猜你喜欢
  • 2013-04-28
  • 1970-01-01
  • 2021-10-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-03
相关资源
最近更新 更多