Python - 有效地处理大型列表

时间:2016-08-28 23:10:12

标签: python python-2.7 permutation itertools anagram

我在 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)

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

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

虽然我有几个潜在解决方案

  1. 创建一些空列表,这些列表只能容纳一定数量的附加permeations。一旦这些列表“完整”,就会将排列添加到下一个列表中。然后根据文本文件检查每个列表。
  2. 创建循环中包含的一个空列表。生成排列并将其附加到列表中,直到某个可行的数字,然后使用该列表检查文本文件,然后清空自己并附加到下一个排列数。
  3. 生成一定数量的排列的其他方法,然后暂停该过程,同时根据文本文件检查当前生成的过程,并重新开始并重复。
  4. 我对Python开发相当新,但并不知道这些是否可行,或者我将如何将它们应用到我的代码中;关于类似主题的其他问题实际上无法提供帮助。

    如果有人希望看到我的代码到目前为止,我很乐意将其压缩并发布,但为了不再提出这个问题,我会将其删除,除非它&# 39; s要求。 (上面更新)

    谢谢!

2 个答案:

答案 0 :(得分:1)

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

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

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

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)

答案 1 :(得分:0)

这应该有所帮助。 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