【问题标题】:Find max length word from arbitrary letters从任意字母中查找最大长度的单词
【发布时间】:2010-08-04 04:31:07
【问题描述】:

我有 10 个任意字母,需要检查单词文件中的最大长度匹配

  1. 前段时间才开始学习RE,似乎找不到合适的模式

    • 第一个想法是使用 set: [10 chars] 但它也重复包含字符,我不知道如何避免这种情况
  2. 我最近开始学习 Python,但在 RE 之前,也许不需要 RE,没有它也可以解决这个问题

    • 使用“for this in that:”迭代器似乎不合适,但也许 itertools 可以轻松完成(我不熟悉)

我猜即使是新手程序员/脚本编写者也知道解决方案,但我不知道 谢谢

【问题讨论】:

  • 您能否举例说明您正在寻找什么样的匹配?当您说最大长度匹配 10 个字母时,您是指仅使用这 10 个字母的混合或仅使用 10 个字母中的一个字母的延伸的最大长度单词(即 aaaaa 是匹配项,但如果您的字母表为 abcde 则不是10 个字母 = {abcdefghij}。另外,这 10 个字母中的每一个都可以只使用一次,或者任意次数。
  • 示例:在这种情况下,我将“ALECETRONE”作为参数传递并获取最大长度的单词,例如“ELECTRON”。字母只使用一次

标签: python puzzle iterator


【解决方案1】:

我猜这就像在给定一组 Scrabble 拼字游戏的情况下找到可能的单词,这样一个字符只能重复在原始列表中重复的次数。

诀窍是针对包含源字母的集合有效地测试单词文件中每个单词的每个字符。对于每个字符,如果在测试集中找到,则将其从测试集中删除并继续;否则,该词不匹配,继续下一个词。

Python 有一个很好的函数all 用于根据序列中的元素测试一组条件。 all 具有“短路”的附加功能,即一旦一个项目不符合条件,则不再进行测试。因此,如果您的候选词的第一个字母是“z”,而您的源字母中没有“z”,那么测试候选词中的任何其他字母就没有意义了。

我第一次写这篇文章很简单:

matches = []
for word in wordlist:
    testset = set(letters)
    if all(c in testset for c in word):
        matches.append(word)

不幸的是,这里的错误是如果源字母包含单个“m”,则带有多个“m”的单词会错误地匹配,因为每个“m”会单独匹配源测试集中给定的“m”。所以我需要删除每个匹配的字母。

我利用set.remove(item) 返回None(Python 将其视为布尔值False)这一事实,并扩展了用于调用all 的生成器表达式。对于 word 中的每个 c,如果在测试集中找到它,我想另外将其从测试集中删除,例如(伪代码,无效 Python):

all(c in testset and "remove c from testset" for c in word)

由于 set.remove 返回 None,我可以将上面引用的位替换为“not testset.remove(c)”,现在我有了一个有效的 Python 表达式:

all(c in testset and not testset.remove(c) for c in word)

现在我们只需将其包装在一个循环中,检查列表中的每个单词(确保在检查每个单词之前构建一个新的测试集,因为我们的 all 测试现在已成为破坏性测试):

for word in wordlist:
    testset = set(letters)
    if all(c in testset and not testset.remove(c) for c in word):
        matches.append(word)

最后一步是按长度降序对匹配项进行排序。我们可以传递一个关键函数来排序。内置 len 会很好,但这会按长度升序排序。要将其更改为降序排序,我们使用 lambda 给我们的不是len,而是-1 * len

matches.sort(key=lambda wd: -len(wd))

现在您可以在matches[0]处打印出最长的单词,或者遍历所有匹配项并将它们打印出来。

(我很惊讶这种蛮力方法运行得如此之好。我使用了 2of12inf.txt 单词列表,包含超过 80,000 个单词,对于 10 个字符的列表,我在大约 0.8 秒内得到匹配列表我的小 1.99GHz 笔记本电脑。)

【讨论】:

  • +1 感谢您的精彩回答和精彩的演讲,但不幸的是我无法让它匹配任何东西。这是我的简单代码(用 6 个字母而不是 10 个字母):pastebin.com/EXU9yFTK 我从未使用过 all() 函数,但我不确定我是否再次清楚该任务,所以我会再尝试一次解释: 假设你有 10 个字母,你的任务是找出你可以用这些字母组成的最长单词。有时最长的单词会是 8 个字母,有时或多或少我会尝试让它对我有用并发布我的结果
  • 您正在使用 readlines() 来获取 dict.dat 的内容。此函数将 '\n' 附加到每一行。尝试 read().splitlines() 代替。
  • :) 完美!我还有一位英雄——保罗·麦奎尔。谢谢,我很高兴它现在可以工作了,这要归功于您的慷慨帮助以及包含在几行代码中的优雅而快速的解决方案:)
  • 如果我看得更远,那是因为我站在巨人的脚趾上。很高兴它成功了! :)
  • 为了记录和娱乐:我用 PYS60 在我的旧诺基亚 E61i(大约 P1:64MB RAM,220 MHz ARM)上运行脚本,输出结果不到 2 分钟: )
【解决方案2】:

我认为这段代码可以满足您的需求:

>>> words = open('file.txt')
>>> max(len(word) for word in set(words.split()))

如果您需要更复杂的标记,例如,如果您不使用拉丁文本,则应使用NLTK

>>> import nltk
>>> words = open('file.txt')
>>> max(len(word) for word in set(nltk.word_tokenize(words)))

【讨论】:

  • 您只是在单词文件中找到最长的单词。我认为他正在尝试寻找字谜。
  • 啊,我明白了.. /me 检查问题
【解决方案3】:

我假设您正在尝试从您的 10 个任意字母中找出最长的单词是什么。

您可以将 10 个任意字母连同它们出现的频率一起保存在一个字典中。

例如,您的 4(为简单起见使用 4 而不是 10)任意字母是:e、w、l、l。这将在一个字典中: {'e':1, 'w':1, 'l':2}

然后对于文本文件中的每个单词,查看该单词的所有字母是否可以在您的任意字母字典中找到。如果是这样,那么这就是你的候选词之一。

所以: 我们 墙 好吧

井中的所有字母都可以在您的任意字母字典中找到,因此请保存它及其长度以便与其他单词进行比较。

【讨论】:

  • 感谢所有答案,是的,我试图解决的就是这种情况 Word 文件有 400,000 个单词,我正在寻找合适的迭代器算法。这是列表:“l = open('dict.dat','r').readlines()”
猜你喜欢
  • 1970-01-01
  • 2015-06-26
  • 2014-05-04
  • 2018-04-02
  • 1970-01-01
  • 2021-08-04
  • 2016-01-21
  • 1970-01-01
  • 2021-12-14
相关资源
最近更新 更多