簡體   English   中英

通過一組字母創建所有可能的基於字典的單詞-改進處理速度的提示

[英]Create all possible dictionary-based words from a set of letters - Tips to improve processing speed

我有一個小項目,我必須解讀(找到所有可能只用一組字母中的一個字母才能寫的單詞)100 000個字母集,每個字母集包含12個字母。 我想找到在Python中處理此任務的速度方面的最佳方法。 到目前為止,我已經花了10個小時,但是命令尚未完成運行。

我看過其他帖子中的確切問題,並從itertools中看到了排列方法。 我認為這比我從網站(以下代碼)借用的這種方法要慢得多。 實際上,對12個字母的字母集進行一次排列已為我的筆記本電腦花費了大量時間。 也許我誤會了一些東西。

我正在使用的字典是西班牙語。 出於演示目的,我將字母集生成為1個字符串,而不是列表。

letters = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','ñ','o','p','q','r','s','t','u','v','w','x','y','z','á','é','í','ó','ú','ü']

def randomString(stringLength=12):
    """Generate a random string of fixed length """
    return ''.join(random.choice(letters) for i in range(stringLength))

定義解密功能

def charCount(word):
    dict = {}
    for i in word:
        dict[i] = dict.get(i, 0) + 1
    return dict


def possible_words(vocab, letterset):
    unscrambled_words = []
    for word in vocab:
        flag = 1
        chars = charCount(word)
        for key in chars:
            if key not in letterset:
                flag = 0
            else:
                if letterset.count(key) != chars[key]:
                    flag = 0
        if flag == 1:
            unscrambled_words.append(word)
    return unscrambled_words

vocab:是一本字典,包含約170 000個單詞。 我把這些詞放在Python列表中。

letteret:是字母列表。 例如:['x','d','a','a','o','u','e','g','g','m','n','f “]。

以下代碼運行了10個小時,但尚未完成。 在我輸入此信息時,它仍在運行。

unscrambled_list = []
for i in range(0,100000):
    possib_words = possible_words(es_vocab,list(letterset_list[i]))
    unscrambled_list.append(possib_words)

詞匯詞典示例: es_vocab = ['ame', 'amo', 'año', 'apio', 'ema', 'empaño', 'me', 'mi', 'miope', 'opima', 'paño', 'pe', 'peña', 'pi', 'pia', 'pie', 'piña', 'pio', 'poema', 'a', 'o', 'e', 'xl', 'kl', 'ml'] #最后3個值不是實際單詞

示例字母集:

letterset_list = ['oiwóeaópñmóó']

如果有人向我展示了完成此任務的更快方法,那就太好了!

es_vocab = ['ame', 'amo', 'año', 'apio', 'ema', 'empaño', 'me', 'mi', 'miope', 'opima', 'paño', 'pe', 'peña', 'pi', 'pia', 'pie', 'piña', 'pio', 'poema', 'a', 'o', 'e', 'xl', 'kl', 'ml']

from itertools import combinations

def generate_key(w):
    out = []
    for ch in set(w):
        out.append( (ch, w.count(ch)) )
    return out

#build index
index = {}
for word in es_vocab:
    index.setdefault(frozenset(generate_key(word)), []).append(word)

letterset_list = ['oiwóeaópñmóó']

seen_substrings = set()
for x in letterset_list:
    all_substrings = (''.join(l) for i in range(len(x)) for l in combinations(x, i+1))
    for substring in all_substrings:
        substring = ''.join(sorted(substring))
        if substring in seen_substrings:
            continue
        seen_substrings.add(substring)
        key = frozenset(generate_key(substring))
        if not key in index:
            continue
        for word in index[key]:
            print(word)

打印:

o
e
a
pi
mi
pe
me
pio
año
amo
pie
pia
ame
ema
apio
paño
piña
peña
miope
opima
poema
empaño

編輯:生成100_000 lettersets和檢查他們反對es_vocab把我的機器上:

real    10m42,351s
user    10m38,069s
sys 0m3,854s

編輯2:現在可以正確處理帶有重復字母的單詞。

def charCount(s):
    s = s.lower()
    answer = [0]*26
    for char in s: answer[ord(char)-97] += 1
    return tuple(answer)


def preprocess(vocab):
    answer = collections.defaultdict(list)
    for word in vocab: answer[charCount(word)].append(word)
    return answer


def possible_words(vocab, scrambled):
    '''note that the `vocab` parameter is actually intended to be preceprocess(list_of_dictionary_words)'''

    return vocab[charCount(scrambled)]

def get_all_possible_words(vocab, lettersets):
    vocab = preprocess(vocab)
    answer = {}
    for letterset in lettersets:
        answer[tuple(letterset)] = possible_words(vocab, letterset)
    return answer

我可能會這樣處理:

def contains_word(letters, word):
    return all(char in letters for char in word)

並確保letters是一set

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM