Создайте два словаря, перебирая функцию, которая возвращает кортеж из двух элементов в Python - PullRequest
1 голос
/ 02 июля 2019

Я хочу создать два словаря в Python путем словарного понимания одновременно. Два словаря используют один и тот же набор ключей, но имеют разные значения для каждого ключа. Поэтому я использую функцию для возврата кортежа из двух значений, и надеюсь, что понимание словаря может создать эти два словаря одновременно.

Скажи, у меня есть функция

def my_func(foo):
    blablabla...
    return a, b

И я создам два словаря по

dict_of_a, dict_of_b = ({key:my_func(key)[0]}, {key:my_func(key)[1]} for key in list_of_keys)

Есть ли лучший код для его улучшения? На мой взгляд, my_func (key) будет вызываться дважды в каждой итерации, что замедляет код. Как правильно это сделать?

Ответы [ 5 ]

1 голос
/ 02 июля 2019
for key in list_of_keys:
   dict_of_a[key],dict_of_b[key] = my_func(key)
0 голосов
/ 03 июля 2019

Обычный цикл, вероятно, лучший путь.Если вы хотите поиграть с functools, вы можете написать:

>>> def func(foo): return foo[0], foo[1:]
... 
>>> L = ['a', 'ab', 'abc']
>>> functools.reduce(lambda acc, x: tuple({**d, x: v} for d, v in zip(acc, func(x))), L, ({}, {}))
({'a': 'a', 'ab': 'a', 'abc': 'a'}, {'a': '', 'ab': 'b', 'abc': 'bc'})

Функция reduce является фолдом: она берет текущий аккумулятор (здесь создаются дикты) и следующее значение из L:

  • d, v in zip(acc, func(x)) извлекает дикты по одному за раз, а соответствующий элемент возвращаемого значения func;
  • {**d, x: v} обновляет dict текущимзначение.

Я не рекомендую такой код, поскольку его трудно поддерживать.

0 голосов
/ 02 июля 2019

С заказано нарезка:

def myfunc(k):
    return k + '0', k + '1'

list_of_keys = ['a', 'b', 'c']

groups = [(k,v) for k in list_of_keys for v in myfunc(k)]
dict_of_a, dict_of_b = dict(groups[::2]), dict(groups[1::2])

print(dict_of_a)   # {'a': 'a0', 'b': 'b0', 'c': 'c0'}
print(dict_of_b)   # {'a': 'a1', 'b': 'b1', 'c': 'c1'}
0 голосов
/ 02 июля 2019

Вы не можете создать два слова в одном понимании.Если ваша основная цель - просто вызвать my_func один раз для создания обоих диктов, используйте для этого функцию:

def mkdicts(keys):

    dict_of_a = {}
    dict_of_b = {}

    for key in keys:
        dict_of_a[key], dict_of_b[key] = my_func(key)

    return dict_of_a, dict_of_b
0 голосов
/ 02 июля 2019

my_func (ключ) будет вызываться дважды на каждой итерации, что замедляет код

Не беспокойтесь об этом.Если вам не нужно выполнять тысячи / миллионы итераций, а выполнение сценария занимает неоправданно много времени, вам не следует беспокоиться о незначительном выигрыше в оптимизации.

Тем не менее, я бы использовал что-то вроде этого:

if __name__ == '__main__':
    def my_func(k):
        return f'a{k}', f'b{k}'


    keys = ['x', 'y', 'z']

    results = (my_func(k) for k in keys)
    grouped_values = zip(*results)
    da, db = [dict(zip(keys, v)) for v in grouped_values]

    print(da)
    print(db)

# Output:
# {'x': 'ax', 'y': 'ay', 'z': 'az'}
# {'x': 'bx', 'y': 'by', 'z': 'bz'}

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