Как оптимизировать циклы, которые повторяют массивные словари с различными значениями размера? - PullRequest
0 голосов
/ 15 марта 2019

Это мой первый пост здесь, я надеюсь, что кто-то может помочь мне с этим.

У меня есть огромный словарь под названием «привет» (> 2 миллиона ключей). Этот словарь имеет значения разных размеров (некоторые списки, другие просто одно значение). Я должен перебрать весь словарь, чтобы получить следующие значения:

portfolios = {k:v for k,v in hello.items() if '.some_list' in k}
hello_deltas = {k:v for k,v in hello.items() if '/delta[' or '/fast_spot[' or '/composite_delta_fx[' in k}

hello_before = {k:v for k,v in hello_deltas.items() if '_0_result' in k}
some_list_before = {}

for some_list in portfolios.values():

    for some in some_list:

        a = [i for i in hello_before.keys() if str(some) in i]

        if len(a) != 0:

            some_list_before[some] = a



hello_after = {k:v for k,v in hello_deltas.items() if '_1_result' in k}
some_list_after = {}

for some_list in portfolios.values():

    for some in some_list:

        a = [i for i in hello_after.keys() if str(some) in i]

        if len(a) != 0:

            some_list_after[some] = a

Я уже много думал об этом и превратил его в мега-комбинацию словарей понимания. ОДНАКО, этого недостаточно.

Я также пытался сделать все в pandas dataframes, но так как размеры значений словаря не совпадают, я не могу построить dataframe!

Может кто-нибудь помочь мне с этим?

1 Ответ

0 голосов
/ 18 марта 2019

Во-первых, вы должны использовать функции, чтобы избежать избыточности:

def before_after(hello, result):
    """result = '_0_result' (before) or '_1_result' (after)"""
    portfolios = {k:v for k,v in hello.items() if '.some_list' in k}
    hello_deltas = {k:v for k,v in hello.items() if '/delta[' or '/fast_spot[' or '/composite_delta_fx[' in k}
    hello_before_after = {k:v for k,v in hello_deltas.items() if result in k}
    some_list_before_after = {}
    for some_list in portfolios.values():
        for some in some_list:
            a = [i for i in hello_before_after.keys() if str(some) in i]
            if len(a) != 0:
                some_list_before_after[some] = a
    return some_list_before_after

Затем, прежде чем погрузиться в понимание списка, посмотрите на код: вы создаете промежуточный словарь, но вы можете использовать генератор:

portfolios_lists = (v for k,v in hello.items() if '.some_list' in k)
for some_list in portfolios_lists:
    for some in some_list:
        ...

Или, лучше:

portfolios_somes = (s for k,v in hello.items() for s in v if '.some_list' in k)
for some in portfolios_somes:
    ...

Вы используете только ключи от hello_deltas:

hello_deltas_before_after = [k for k in hello.keys() if result in k and ('/delta[' or '/fast_spot[' or '/composite_delta_fx[' in k)]

Примечание: с функцией вы можете подумать, что вы будете проверять, если'/delta[' or '/fast_spot[' or '/composite_delta_fx[' in k дважды: один для before и один для after.На самом деле это не так: сначала вы проверяете, стоит ли result in k (то есть '_0_result' in k или '_0_result' in k) и , а затем сделать дорогостоящий тест.

Код теперь выглядит следующим образом:

def before_after(hello, result):
    portfolios_somes = (s for k,v in hello.items() for s in v if '.some_list' in k)
    hello_deltas_before_after = [k for k in hello.keys() if result in k and ('/delta[' or '/fast_spot[' or '/composite_delta_fx[' in k)]
    some_list_before_after = {}
    for some in portfolios_somes:
        a = [i for i in hello_deltas_before_after if str(some) in i]
        if len(a) != 0:
            some_list_before_after[some] = a
    return some_list_before_after

Теперь, определение слова:

some_list_before_after = {
    some: a 
    for some in portfolios_somes 
    for a in ([i for i in hello_deltas_before_after if str(some) in i], ) 
    if a}

Кортеж из одного элемента - это трюк для вычисления a только один раз.Полный код (не проверено):

def before_after(hello, result):
    portfolios_somes = (s for k, v in hello.items() for s in v if '.some_list' in k)
    hello_deltas_before_after = [k for k in hello.keys() if result in k and ('/delta[' or '/fast_spot[' or '/composite_delta_fx[' in k)]
    return {
        some: a 
        for some in portfolios_somes 
        for a in ([i for i in hello_deltas_before_after if str(some) in i], ) 
        if a}

Это должно быть быстрее, чем оригинальная версия, но проблема имеет (очень приблизительно) O (n ^ 2) временную сложность, и вы не получите результат турачерез секунду.Попробуйте это на подмножестве исходных данных (например, hello_short = dict(itertools.islice(hello.items(), 1000))).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...