Вложенные выражения генератора в список аргументов для вызова функции python
-
06-07-2019 - |
Вопрос
Мне нравится использовать следующую идиому для объединения списков, иногда:
>>> list(itertools.chain(*[[(e, n) for e in l] for n, l in (('a', [1,2]),('b',[3,4]))]))
[(1, 'a'), (2, 'a'), (3, 'b'), (4, 'b')]
(Я знаю, что есть более простые способы получить этот конкретный результат, но он пригодится, когда вы хотите перебрать элементы в списках списков списков или что-то в этом роде. Проблема в том, что при использовании генератора выражения, это становится подверженным ошибкам. Например,
>>> list(itertools.chain(*(((e, n) for e in l) for n, l in (('a', [1,2]),('b',[3,4])))))
[(1, 'b'), (2, 'b'), (3, 'b'), (4, 'b')]
Здесь происходит то, что выражения внутреннего генератора передаются в качестве аргументов itertools.chain
, поэтому во время их вычисления выражение внешнего генератора завершено и n
фиксируется в своем окончательном значении, 'b'
. Мне интересно, думал ли кто-нибудь о способах избежать такого рода ошибок, кроме как "не делай этого".
Решение
Ваш подход почти работает, вам просто нужно сгладить генераторы. Посмотрите, как для e в l
перемещается в крайнее правое положение
>>> list(itertools.chain((e, n) for n, l in (('a', [1,2]),('b',[3,4])) for e in l ))
[(1, 'a'), (2, 'a'), (3, 'b'), (4, 'b')]
Вот как сделать то же самое, используя itertools.product
>>> X=itertools.chain(*(itertools.product(*i[::-1]) for i in (('a', [1,2]),('b',[3,4]))))
>>> print list(X)
[(1, 'a'), (2, 'a'), (3, 'b'), (4, 'b')]
или если вам разрешено переключать кортежи
>>> X=itertools.chain(*(itertools.product(*i) for i in (([1,2],'a'),([3,4],'b'))))
>>> print list(X)
[(1, 'a'), (2, 'a'), (3, 'b'), (4, 'b')]
Другие советы
Разве понимание вложенного списка не будет более подходящим?
>>> tt = (('a', [1,2]),('b',[3,4]))
>>> [(s, i) for i, l in tt for s in l]
[(1, 'a'), (2, 'a'), (3, 'b'), (4, 'b')]
Я собираюсь предложить
data = (('a', [1,2]), ('b', [3,4]))
result = []
for letter, numbers in data:
for number in numbers:
result.append((number, letter))
Это намного удобнее для чтения, чем ваша семья решений. Фантазии не очень хорошая вещь.