Эффективная фильтрация данных по нескольким переменным в Python

#python #list-comprehension

#python #понимание списка

Вопрос:

Как бы я мог более эффективно выполнять следующие действия, не повторяя дважды сжатый список:

 x = [(item1['a'], item2) for item1, item2 in zip(foo, bar)]
y = [item2.replace(item1['b'], '') for item1, item2 in zip(foo, bar)]
  

Комментарии:

1. Если я чего-то не упускаю, просто не используйте понимание списка. Инициализируйте x и y, затем выполните цикл for с zip. Внутри одного-единственного цикла for добавляйте как к x, так и к y.

Ответ №1:

Немного менее Pythonic:

 x = []
y = []
for item1,item2 in zip(foo,bar):
    x.append((item1['a'],item2))
    y.append(item2.replace(item1['b'],''))
  

Комментарии:

1. почему это менее pythonic? 🙂

2. @Tomerikoo: это всего лишь мое мнение 😉

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

Ответ №2:

В общем, вы можете использовать выражение генератора для вывода нескольких значений в виде кортежей, а затем zip преобразовать последовательность кортежей в отдельные последовательности, чтобы вы могли распаковать их в отдельные переменные.

Поэтому вместо, например:

 x = [i   1 for i in lst]
y = [i   2 for i in lst]
  

Вы можете сделать:

 x, y = zip(*((i   1, i   2) for i in lst))
  

Однако в этом случае x и y станут кортежами, поэтому, если вам нужно, чтобы x и y были настоящими списками, вместо этого вы можете map последовательность вывода в list конструктор:

 x, y = map(list, zip(*((i   1, i   2) for i in lst)))
  

Таким образом, утверждения в вашем вопросе могут быть переписаны как:

 x, y = map(list, zip(*(((item1['a'], item2), item2.replace(item1['b'], '')) for item1, item2 in zip(foo, bar))))
  

Комментарии:

1. Они выводятся в виде кортежей, а не списков.