В информатике zipping — это функция , которая отображает кортеж последовательностей в последовательность кортежей . Это название zip происходит от действия zipper , который чередует две ранее непересекающиеся последовательности. Обратная функция — unzip .
Даны три слова cat , fish и be , где | cat | равно 3, | fish | равно 4 и | be | равно 2. Пусть обозначает длину самого длинного слова, которым является fish ; . ZIP-код cat , fish , be тогда равен 4 кортежам элементов:
где # — символ, которого нет в исходном алфавите. В Haskell это усекает до самой короткой последовательности , где :
zip3 "кот" "рыба" "быть" -- [('c','f','b'),('a','i','e')]
Пусть Σ — алфавит , # — символ, не входящий в Σ.
Пусть x 1 x 2 ... x | x | , y 1 y 2 ... y | y | , z 1 z 2 ... z | z | , ... будут n словами (т. е. конечными последовательностями ) элементов Σ. Пусть обозначает длину самого длинного слова, т. е. максимум из | x |, | y |, | z |, ... .
Zip этих слов представляет собой конечную последовательность из n -кортежей элементов (Σ ∪ {#}) , т.е. элемент :
где для любого индекса i > | w | , w i равно #.
Индекс x, y, z, ... обозначается как zip( x, y, z, ... ) или x ⋆ y ⋆ z ⋆ ...
Обратное к zip иногда обозначается как unzip.
Разновидность операции zip определяется следующим образом:
где — минимальная длина входных слов. Это позволяет избежать использования присоединенного элемента , но уничтожает информацию об элементах входных последовательностей за пределами .
Функции zip часто доступны в языках программирования , часто называемых zip . В диалектах Lisp можно просто отобразить нужную функцию по нужным спискам, map является вариативной в Lisp, поэтому она может принимать произвольное количество списков в качестве аргумента. Пример из Clojure : [1]
;; `nums' содержит бесконечный список чисел (0 1 2 3 ...) ( def nums ( range )) ( def tens [ 10 20 30 ]) ( def firstname "Alice" ) ;; Чтобы сжать (0 1 2 3 ...) и [10 20 30] в вектор, вызовите для них `map vector'; то же самое со списком ( map vector nums tens ) ; ⇒ ([0 10] [1 20] [2 30]) ( map list nums tens ) ; ⇒ ((0 10) (1 20) (2 30)) ( map str nums tens ) ; ⇒ ("010" "120" "230") ;; `map' усекает до самой короткой последовательности; обратите внимание, что в "Alice" отсутствуют \c и \e ( map vector nums tens firstname ) ; ⇒ ([0 10 \A] [1 20 \l] [2 30 \i]) ( map str nums tens firstname ) ; ⇒ ("010A" "120l" "230i") ;; Чтобы распаковать, примените `map vector' или `map list' ( apply map list ( map vector nums tens firstname )) ;; ⇒ ((0 1 2) (10 20 30) (\A \l \i))
В Common Lisp :
( defparameter nums ' ( 1 2 3 )) ( defparameter tens ' ( 10 20 30 )) ( defparameter firstname "Alice" ) ( mapcar #' список чисел десятков ) ;; ⇒ ((1 10) (2 20) (3 30)) ( mapcar #' list nums tens ( coerce firstname 'list )) ;; ⇒ ((1 10 #\A) (2 20 #\l) (3 30 #\i)) — усечение по самому короткому списку ;; Распаковывает ( apply #' mapcar #' list ( mapcar #' list nums tens ( coerce firstname 'list ))) ;; ⇒ ((1 2 3) (10 20 30) (#\A #\l #\i))
Такие языки, как Python, предоставляют функцию zip() . [2] zip() в сочетании с оператором * распаковывает список: [2]
>>> числа = [ 1 , 2 , 3 ] >>> десятки = [ 10 , 20 , 30 ] >>> имя = 'Алиса'>>> сжато = список ( zip ( цифры , десятки )) >>> сжато [(1, 10), (2, 20), (3, 30)]>>> список ( zip ( * сжато )) # распаковать [(1, 2, 3), (10, 20, 30)]>>> zipped2 = list ( zip ( nums , tens , list ( firstname ))) >>> zipped2 # zip, усечение по кратчайшему [(1, 10, 'A'), (2, 20, 'l'), (3, 30, 'i')] >>> list ( zip ( * zipped2 )) # распаковать [(1, 2, 3), (10, 20, 30), ('A', 'l', 'i')]
В Haskell есть метод сжатия последовательностей, но для каждой арности требуется определенная функция ( zip для двух последовательностей, zip3 для трех и т. д.), [3] аналогично для распаковки доступны функции unzip и unzip3 :
-- nums содержит бесконечный список чисел [1, 2, 3, ...] nums = [ 1 .. ] tens = [ 10 , 20 , 30 ] firstname = "Alice" zip nums tens -- ⇒ [(1,10), (2,20), (3,30)] — zip, обрезает бесконечный список unzip $ zip nums tens -- ⇒ ([1,2,3], [10,20,30]) — unzip zip3 числа десятки имя -- ⇒ [(1,10,'A'), (2,20,'l'), (3,30,'i')] — zip, усекает unzip3 $ zip3 числа десятки имя -- ⇒ ([1,2,3], [10,20,30], "Ali") — распаковать
Список языков, поддерживаемых zip:
Язык | Почтовый индекс | Архивировать 3 списка | Zip - списки | Примечания |
---|---|---|---|---|
Часовня | zip ( iter1 iter2 ) | zip ( iter1 iter2 iter3 ) | zip ( iter1 ... itern ) | Форма каждого итератора, ранг и экстенты в каждом измерении должны быть идентичны. [4] |
Кложур | (список карт список1 список2 ) (вектор карты список1 список2 ) | (список карт список1 список2 список3 ) (вектор карты список1 список2 список3 ) | (список карт list1 … listn ) (вектор карты list1 … listn ) | Останавливается после длины самого короткого списка. |
Общий Лисп | (mapcar #'list list1 list2) | (mapcar #'list list1 list2 list3) | (mapcar #'list list1 ... listn) | Останавливается после длины самого короткого списка. |
Д | zip( диапазон1 , диапазон2 ) диапазон1.zip ( диапазон2 ) | zip( диапазон1 , диапазон2 , диапазон3 ) диапазон1.zip (диапазон2, диапазон3) | zip( диапазон1 , …, диапазонN ) диапазон1 .zip(…, диапазонN) | Политика остановки по умолчанию установлена на кратчайший путь и может быть опционально указана как кратчайший, длиннейший или требующая той же длины. [5] Вторая форма является примером UFCS . |
Фа# | List.zip список1 список2 Seq.zip источник1 источник2 Array.zip массив1 массив2 | List.zip3 список1 список2 список3 Seq.zip3 источник1 источник2 источник3 Array.zip3 массив1 массив2 массив3 | ||
Хаскелл | почтовый список1 список2 | zip3 список1 список2 список3 | zip n список1 … списокn | zipn для n > 3 доступен в модуле Data.List . Останавливается после окончания самого короткого списка. |
Питон | zip( список1 , список2 ) | zip( список1 , список2 , список3 ) | zip( список1 , …, списокn ) | zip() и map() (3.x) останавливаются после того, как заканчивается самый короткий список, тогда как map() (2.x) и itertools.zip_longest() (3.x) расширяют более короткие спискиэлементами None |
Рубин | список1 .zip( список2 ) | список1 .zip( список2 , список3 ) | список1 .zip( список1 , .., списокn ) | Когда список, выполняемый на (list1), короче, чем сжимаемые списки, результирующий список имеет длину list1. Если list1 длиннее, то для заполнения отсутствующих значений используются нулевые значения [6] |
Скала | список1 .zip( список2 ) | Если одна из двух коллекций длиннее другой, ее оставшиеся элементы игнорируются. [7] |
Язык | Распаковать | Распаковать 3 кортежа | Распаковать n кортежей | Примечания |
---|---|---|---|---|
Кложур | (применить векторную карту ziplist ) | (применить векторную карту ziplist ) | (применить векторную карту ziplist ) | |
Общий Лисп | (apply #'mapcar #'list ziplist) | (apply #'mapcar #'list ziplist) | (apply #'mapcar #'list ziplist) | |
Фа# | List.unzip list1 list2 Seq.unzip source1 source2 Array.unzip array1 array2 | List.unzip3 list1 list2 list3 Seq.unzip3 source1 source2 source3 Array.unzip3 array1 array2 array3 | ||
Хаскелл | распаковать ziplist | unzip3 ziplist | распаковать и заархивировать | unzipn для n > 3 доступен в модуле Data.List . |
Питон | zip(* zipvlist ) | zip(* zipvlist ) | zip(* zipvlist ) |