python - однострочный, вложенный в циклы - PullRequest
0 голосов
/ 15 сентября 2018

Каким будет Python-однострочный эквивалент приведенного ниже кода?

l=[]
for i in range(3,5) :
    if i==3:
        for j in range(0,2):
            if i%2:
                l.append(i*j)
            else:
                l.append(i+j)
    else:
        l.append(i)
print(l)

Я пытался использовать одну строку для вложенного цикла, но только с одним условием, подобным этому:

print([i*j if i%2 else i+j for i in range(3,5) for j in range(0,2)])

ПримечаниеЗдесь я хочу узнать, как использовать однострочный эквивалент для вложенных циклов с условием if else в обоих циклах.Также, если это невозможно, укажите, почему нет!

Заранее спасибо:)

Ответы [ 5 ]

0 голосов
/ 18 сентября 2018

Вот что я придумал: print(list(set([i*j if i % 2 else i+j if i==3 else i for i in range(3, 5) for j in range(0, 2)])))

0 голосов
/ 16 сентября 2018

Вы можете преобразовать свою внутреннюю часть в последовательность списков:

[[i * j if i % 2 else i + j for j in range(2)] if i == 3 else [i] for i in range(3,5)]

Развертывание 2D-итерации легко в общем случае:

[e for row in iterable for e in row]

Объединение двух:

[e for row in [[i * j if i % 2 else i + j for j in range(2)] if i == 3 else [i] for i in range(3,5)] for e in row]

Вы можете избежать хранения промежуточных списков, используя генераторы:

[e for row in ((i * j if i % 2 else i + j for j in range(2)) if i == 3 else [i] for i in range(3,5)) for e in row]
0 голосов
/ 16 сентября 2018

Я придумал, чтобы сгенерировать последовательность для каждого i, а затем объединить понимание, чтобы объединить их в один список:

[x for y in ((i*j if i%2 else i+j for j in range(0, 2)) if i == 3 else (i,) for i in range(3, 5)) for x in y]
# [0, 3, 4]

Очевидно, что это намного сложнее и труднеечитать, чем вложенная версия, и, вероятно, работает хуже.

0 голосов
/ 16 сентября 2018

Вот чудовищное чудовище, которое делает это:

[x for i in range(3,5) for x in ([i*j if i%2 else i+j for j in range(2)] if i==3 else (i,))]

Я стараюсь сделать это читабельным:

In [12]: result = [
    ...:     x
    ...:     for i in range(3, 5)
    ...:     for x in ((i*j if i%2 else i+j for j in range(2))
    ...:               if i ==3 else (i,))
    ...: ]

In [13]: print(result)
[0, 3, 4]

Как указано в комментариях, ваше зацикливание не должно быть таким сложным. Вы должны использовать функции здесь, чтобы сделать ваш код более читабельным. Это также сделает использование списочных представлений менее громоздким. Ваша цель не должна быть «держать вещи на одной линии». Ваша цель должна заключаться в том, чтобы "сделать мой код читабельным, понятным, простым и честным". Это понимание списка не является чем-то подобным.

Обратите внимание, я не ожидаю, что это будет работать лучше. Это требует создания дополнительных анонимных контейнеров или генераторов \ списков-пониманий (что требует создания и вызова объекта функции изнутри).

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

0 голосов
/ 16 сентября 2018

Я бы начал с попытки что-то вроде следующего:

[(i*j if i % 2 and i==3
  else i+j if i==3
  else i)
 for j in range(0, 2)
 for i in range(3, 5)]

Синтаксис понимания вложенного списка может быть довольно запутанным. Это вывод:

[0, 4, 3, 4]

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

result = list(set(result))
# where result is the list above 

[0, 3, 4]
...