В программе, которую я пишу, возникла необходимость повернуть двумерный массив. В поисках оптимального решения я нашел этот впечатляющий однострочный текст, который выполняет свою работу:
rotated = zip(*original[::-1])
Сейчас я использую его в своей программе, и он работает как положено. Но моя проблема в том, что я не понимаю, как это работает.
Я был бы признателен, если бы кто-нибудь мог объяснить, как различные задействованные функции достигают желаемого результата.
python
multidimensional-array
paldepind
источник
источник
Ответы:
Рассмотрим следующий двумерный список:
Давайте разберем это шаг за шагом:
Этот список передается
zip()
при использовании распаковки аргументов , поэтомуzip
вызов оказывается эквивалентом этого:Надеюсь, комментарии прояснят, что
zip
делает, он группирует элементы из каждого итерируемого ввода на основе индекса, или, другими словами, он группирует столбцы.источник
rotated = [list(r) for r in zip(*original[::-1])]
Это умно.
Во-первых, как указано в комментарии, в Python 3
zip()
возвращается итератор, поэтому вам нужно заключить все это,list()
чтобы получить реальный список обратно, так что с 2020 года это на самом деле:Вот разбивка:
[::-1]
- делает мелкую копию исходного списка в обратном порядке. Можно также использовать,reversed()
который будет производить обратный итератор по списку, а не фактическое копирование списка (более эффективное использование памяти).*
- делает каждый подсписок в исходном списке отдельным аргументом дляzip()
(т.е. распаковывает список)zip()
- берет по одному элементу из каждого аргумента и составляет из них список (ну, кортеж) и повторяется, пока не будут исчерпаны все подсписки. Вот где на самом деле происходит транспозиция.list()
преобразует выводzip()
в список.Итак, если у вас есть это:
Сначала вы получите это (неглубокая перевернутая копия):
Затем каждый из подсписок передается в качестве аргумента
zip
:zip()
многократно потребляет по одному элементу с начала каждого из своих аргументов и создает из него кортеж, пока не кончатся элементы, в результате чего (после преобразования в список):А Боб твой дядя.
Чтобы ответить на вопрос @IkeMiguel в комментарии о его вращении в другом направлении, это довольно просто: вам просто нужно отменить как последовательность, которая входит, так
zip
и результат. Первое может быть достигнуто, удалив,[::-1]
а второе может быть достигнуто, разбросав всеreversed()
вокруг. Такreversed()
как по списку возвращается итератор, нам нужно будет егоlist()
обойти , чтобы преобразовать. С парой дополнительныхlist()
вызовов для преобразования итераторов в реальный список. Так:Мы можем немного упростить это, используя срез "марсианского смайлика", а не
reversed()
... тогда нам не понадобится внешнийlist()
:Конечно, вы также можете просто повернуть список по часовой стрелке три раза. :-)
источник
zip
в список в Python 3.x!Это состоит из трех частей:
источник
Просто наблюдение. Входные данные - это список списков, но результат очень красивого решения: rotated = zip (* original [:: - 1]) возвращает список кортежей.
Это может быть, а может и не быть проблемой.
Однако это легко исправить:
Композиция списка или карта преобразуют внутренние кортежи обратно в списки.
источник
источник
У меня сама была эта проблема, и я нашел отличную страницу в Википедии по этой теме (в абзаце «Общие вращения»:
https://en.wikipedia.org/wiki/Rotation_matrix#Ambiguities
Затем я написал следующий код, очень подробный, чтобы иметь четкое представление о том, что происходит.
Я надеюсь, что вы сочтете полезным копать больше в очень красивом и умном однострочном сообщении, которое вы разместили.
Чтобы быстро протестировать его, вы можете скопировать / вставить его здесь:
http://www.codeskulptor.org/
источник
Поворот против часовой стрелки (стандартный столбец для поворота строки) в виде списка и словаря
Производит:
источник
zip(*original[::-1])
работает.