【问题标题】:Python - Efficiently working with large permutated listsPython - 有效地处理大型排列列表
【发布时间】:2017-01-04 21:58:03
【问题描述】:

我在 Python 2.7 中编写了一个简短的 Anagram Solver 脚本。

#Import Permutations Module
from itertools import permutations as perm

#Defined Functions
def check(x,y):

    #Opens Dictionary File
    with open('wordsEn.txt') as dictionary:

        '''Checks the permutations against all of the dictionary words and appends
        any matching ones to on of the empty lists'''

        for line in dictionary:
            for i in x:
                if i + '\n' == line:
                    y.append(i)

#Empty Lists that will be appended to later
anagram_perms = []
possible_words = []

#Anagram User Input
anagram = list(raw_input("Input scrambled word: ").lower())

#Creates single list items from the permutations, deletes duplicates
for char in perm(anagram):
    anagram_perms.append("".join(char))
    anagram_perms = list(set(anagram_perms))

#Uses the defined function
check(anagram_perms, possible_words)

#Prints the number of perms created, then prints the possible words beneath it
print len(anagram_perms)
print '\n'.join(possible_words)

它本质上接受用户输入的字谜,生成所有可能的字母组合并将其放入列表中(使用itertools.permutations),删除所有重复项。然后,它会根据 100000 个单词的字典文本文件检查这些组合中的每一个,将任何匹配的单词放入要打印的列表中。

我遇到的问题是,如果用户输入的单词长度超过 6 个唯一字母,则生成的排列数会导致挂起和崩溃。 9 个字母的字谜将是典型的输入,但显然如果所有字母都不同,这些将输出 362880('9!')排列,这是不可行的。

我想到了几个可能的解决方案

  1. 创建一些空列表,这些列表只能包含一定数量的附加排列。一旦这些列表“满”,就会将排列添加到下一个列表中。随后会根据文本文件检查这些列表中的每一个。
  2. 创建一个包含在循环中的空列表。生成排列并将其附加到列表中,直到达到某个可行的数量,然后列表用于在清空自身并附加到下一个排列数量之前检查文本文件。
  3. 其他方法生成一定数量的排列,然后暂停该过程,同时根据文本文件检查当前生成的排列,然后恢复并重复。

但是,我对 Python 开发还很陌生,我真的不知道这些是否可行,或者我将如何将它们实现到我的代码中;和其他类似主题的问题并没有真正提供帮助。

到目前为止,如果有人想查看我的代码,我很乐意将其压缩并发布,但为了不再提出这个问题,除非有人要求,否则我会将其省略。 (以上更新)

谢谢!

【问题讨论】:

  • 请发布您的代码。
  • 请发布您的代码、代码功能的简要信息(BRIEF)、示例输入和所需输出(或您面临的问题)。否则没有人会读这么多,或者如果有人这样做,他们很难理解。请帮助我们帮助你:)
  • @MoinuddinQuadri ,我不确定添加代码但增加问题长度的好处是否值得并鼓励人们阅读,但可以肯定的是,我会继续浓缩并添加它:)
  • StackOverflow 社区可以帮助您解决问题,但我们也需要了解您为解决问题所做的努力。
  • @MoinuddinQuadri 好的,谢谢,上面更新了:)

标签: python python-2.7 permutation itertools anagram


【解决方案1】:

它认为最好的解决方案可能是不使用排列。大多数生成的排列很可能不是一个单词 - 所以生成它们是一种浪费。

您可以考虑将此字典预处理为已排序字母的字典,以列出这些字母所包含的单词。然后,您的字谜求解器将在对输入进行排序后在字典中进行简单查找。

首先,从您的单词列表中创建字典并保存到文件中:

from collections import defaultdict
import json

word_list = ['tab', 'bat', 'cat', 'rat', ...]  # 100k words
word_dict = defaultdict(list)
for word in word_list:
    word_dict[''.join(sorted(word))].append(word)
with open('word_dict.json') as f:
    f.write(json.dumps(dict(word_dict)))

然后,在运行你的 anagram 代码时,加载字典并使用它来查找排序后的输入:

import json

empty_list = []
with open('word_dict.json', 'r') as f:
    word_dict = json.loads(f.read())

while True:
    anagram = raw_input('Enter in an anagram: ')
    sorted_anagram = ''.join(sorted(anagram))
    print word_dict.get(sorted_anagram, empty_list)

【讨论】:

  • 有趣,我没有考虑过这样看,谢谢!我不认为这正是你所说的,但这让我想知道......我可以简单地编写代码来查看字典文本文件的每一行,并说“如果这一行包含所有输入的字谜”字母按任意顺序一次,然后将其附加到 possible_words 列表中,否则移动到下一行'?
  • 是的,但它会比字典方法慢,因为您必须遍历字典并在每次循环迭代中计算字母。
  • 是的。所以,如果我有这个错误,请纠正我,你是说首先获取输入的字谜的长度并使用它将文本文件中相同长度的所有单词放入字典中,然后检查哪些单词这些单词与字谜具有相同的字母并将它们附加到列表中? :) 你介意在你的代码中添加几个 cmets,因为我认为我不太了解一两件事吗?
  • 啊抱歉,我认为我对 python 的有限知识在这里没有帮助,我仍然没有正确理解它。 100k 单词列表是一个 .txt 文件,你是说我应该先将它们全部附加到列表 (word_list) 中,然后再从那里继续吗?以及导入json 模块有什么好处?
  • 建议使用您的 .txt 文件,并将此文件一次性转换为包含我描述的字典的不同 .json 文件。然后,您应该使用此 .json 文件而不是 .txt 文件。 json 模块可帮助您对字典进行序列化和反序列化。
【解决方案2】:

这应该会有所帮助。 itertools.permutations 函数返回一个迭代器。这意味着整个列表不会存储在内存中;相反,您可以调用下一个值,它会即时计算所需的值。

from itertools import permutations

with open('./wordlist.txt', 'r') as fp:
    wordlist_str = fp.read()
    wordlist = set(wordlist_str.lower().split('\n'))  #use '\r\n' in Windows

def get_anagrams(word):
    out = set()
    for w in permutations(word.lower()):
        if ''.join(w) in wordlist:
            out.add(''.join(w))
    return out

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-02-11
    • 2019-07-30
    • 2016-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多