все соседние комбинации списков, начинающиеся с индекса; переупорядочивание на основе ключей словаря (скорость, python) - PullRequest
0 голосов
/ 17 июня 2020

Учитывая это:

import re
from itertools import islice, chain
from numpy import resize

def adj(l):
    ln = len(l)
    yield l
    for n in range(ln -1, 0, -1):
        yield from (tuple(islice(l, i, n + i)) for i in range(ln - n % ln+1))

lexicon = {('a',): 12, ('a', 'n'): 2, ('h',): 3, ('h', 'i'): 5, 
           ('h', 'i', 'm'): 0, ('h', 'i', 'm', 'a'): 3, ('h', 'i', 'm', 'a', 'n'): 0, 
           ('i',): 0, ('i', 'm'): 4, ('i', 'm', 'a'): 3, ('i', 'm', 'a', 'n'): 0, 
           ('m',): 0, ('m', 'a'): 0, ('m', 'a', 'n'): 0, ('n',): 0}

lexicon = {k: v for k, v in sorted(lexicon.items(), key=lambda x: x[0], reverse = False)}
lexicon = {k: v for k, v in sorted(lexicon.items(), key=lambda x: x[1], reverse = True)}

utterance_split = ['h', 'i', 'm', 'a', 'n']

Я пытаюсь получить все возможные комбинации смежных элементов, которые начинаются с определенного c индекса utterance_split, а затем подмножества словаря на основе этих комбинаций, без изменения исходного порядка словаря. Моя проблема - скорость, потому что код, который я придумал, очень медленный, поскольку он должен перебирать все индексы в utterance_split (а позже и по различным элементам utterance_split, здесь не показаны).

Медленный код указанный ниже результат, который я хотел бы получить (вы можете закомментировать операторы печати, чтобы посмотреть на результат). Как я могу получить тот же результат, используя максимально быстрый код?

for utterance_position in range(0, len(utterance_split)):
    # START SLOW PART
    # return all consecutive combinations of utterance_split

    # a combination always starts at utterance_position

    # combinations are then ordered as how they appear in the lexicon 
        # the lexicon is ordered by alphabetic order first, and then value
    combinations = [list(adj(tuple(re.sub("^", "9", "_".join(utterance_split[utterance_position:])).split("_"))))]
    combinations = sorted(list(set(list(chain(*combinations)))))
    combinations = [tuple(re.sub("^9", "", "_".join(combination)).split("_")) for combination in combinations if "9" in "".join(combination)]
    combinations = {key:lexicon[key] for key in combinations}
    combinations = {k: v for k, v in sorted(combinations.items(), key=lambda x: x[0], reverse = False)}
    combinations = {k: v for k, v in sorted(combinations.items(), key=lambda x: x[1], reverse = True)}
    #print(combinations)
    #print("\n")
    combinations = iter(combinations.items())
    # END SLOW PART

    while True:
        combination = next(combinations)
        # do something
        break
...