Вложенные выражения генератора в список аргументов для вызова функции python

StackOverflow https://stackoverflow.com/questions/1620957

Вопрос

Мне нравится использовать следующую идиому для объединения списков, иногда:

>>> 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))

Это намного удобнее для чтения, чем ваша семья решений. Фантазии не очень хорошая вещь.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top