Zipping (computer science)
Template:Short description Script error: No such module "about". In computer science, zipping is a function which maps a tuple of sequences into a sequence of tuples. This name zip derives from the action of a zipper in that it interleaves two formerly disjoint sequences. The inverse function is unzip.
Example
Given the three words cat, fish and be where |cat| is 3, |fish| is 4 and |be| is 2. Let denote the length of the longest word which is fish; . The zip of cat, fish, be is then 4 tuples of elements:
where # is a symbol not in the original alphabet. In Haskell this truncates to the shortest sequence , where :
zip3 "cat" "fish" "be"
-- [('c','f','b'),('a','i','e')]
Definition
Let Σ be an alphabet, # a symbol not in Σ.
Let x1x2... x|x|, y1y2... y|y|, z1z2... z|z|, ... be n words (i.e. finite sequences) of elements of Σ. Let denote the length of the longest word, i.e. the maximum of |x|, |y|, |z|, ... .
The zip of these words is a finite sequence of n-tuples of elements of (Σ ∪ {#})Script error: No such module "Check for unknown parameters"., i.e. an element of :
- ,
where for any index i > Template:AbsScript error: No such module "Check for unknown parameters"., the wi is #.
The zip of x, y, z, ... is denoted zip(x, y, z, ...) or x ⋆ y ⋆ z ⋆ ...
The inverse to zip is sometimes denoted unzip.
A variation of the zip operation is defined by:
where is the minimum length of the input words. It avoids the use of an adjoined element , but destroys information about elements of the input sequences beyond .
In programming languages
Zip functions are often available in programming languages, often referred to as <templatestyles src="Mono/styles.css" />zip. In Lisp-dialects one can simply <templatestyles src="Mono/styles.css" />map the desired function over the desired lists, <templatestyles src="Mono/styles.css" />map is variadic in Lisp so it can take an arbitrary number of lists as argument. An example from Clojure:[1]
;; `nums' contains an infinite list of numbers (0 1 2 3 ...)
(def nums (range))
(def tens [10 20 30])
(def firstname "Alice")
;; To zip (0 1 2 3 ...) and [10 20 30] into a vector, invoke `map vector' on them; same with list
(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' truncates to the shortest sequence; note missing \c and \e from "Alice"
(map vector nums tens firstname) ; ⇒ ([0 10 \A] [1 20 \l] [2 30 \i])
(map str nums tens firstname) ; ⇒ ("010A" "120l" "230i")
;; To unzip, apply `map vector' or `map list'
(apply map list (map vector nums tens firstname))
;; ⇒ ((0 1 2) (10 20 30) (\A \l \i))
In Common Lisp:
(defparameter nums '(1 2 3))
(defparameter tens '(10 20 30))
(defparameter firstname "Alice")
(mapcar #'list nums tens)
;; ⇒ ((1 10) (2 20) (3 30))
(mapcar #'list nums tens (coerce firstname 'list))
;; ⇒ ((1 10 #\A) (2 20 #\l) (3 30 #\i)) — truncates on shortest list
;; Unzips
(apply #'mapcar #'list (mapcar #'list nums tens (coerce firstname 'list)))
;; ⇒ ((1 2 3) (10 20 30) (#\A #\l #\i))
Languages such as Python provide a <templatestyles src="Mono/styles.css" />zip() function.[2] <templatestyles src="Mono/styles.css" />zip() in conjunction with the <templatestyles src="Mono/styles.css" />* operator unzips a list:[2]
>>> nums = [1, 2, 3]
>>> tens = [10, 20, 30]
>>> firstname = 'Alice'
>>> zipped = list(zip(nums, tens))
>>> zipped
[(1, 10), (2, 20), (3, 30)]
>>> list(zip(*zipped)) # unzip
[(1, 2, 3), (10, 20, 30)]
>>> zipped2 = list(zip(nums, tens, list(firstname)))
>>> zipped2 # zip, truncates on shortest
[(1, 10, 'A'), (2, 20, 'l'), (3, 30, 'i')]
>>> list(zip(*zipped2)) # unzip
[(1, 2, 3), (10, 20, 30), ('A', 'l', 'i')]
Haskell has a method of zipping sequences but requires a specific function for each arity (<templatestyles src="Mono/styles.css" />zip for two sequences, <templatestyles src="Mono/styles.css" />zip3 for three etc.),[3] similarly the functions <templatestyles src="Mono/styles.css" />unzip and <templatestyles src="Mono/styles.css" />unzip3 are available for unzipping:
-- nums contains an infinite list of numbers [1, 2, 3, ...]
nums = [1..]
tens = [10, 20, 30]
firstname = "Alice"
zip nums tens
-- ⇒ [(1,10), (2,20), (3,30)] — zip, truncates infinite list
unzip $ zip nums tens
-- ⇒ ([1,2,3], [10,20,30]) — unzip
zip3 nums tens firstname
-- ⇒ [(1,10,'A'), (2,20,'l'), (3,30,'i')] — zip, truncates
unzip3 $ zip3 nums tens firstname
-- ⇒ ([1,2,3], [10,20,30], "Ali") — unzip
Language comparison
List of languages by support of zip:
| Language | Zip | Zip 3 lists | Zip n lists | Notes |
|---|---|---|---|---|
| Chapel | <templatestyles src="Mono/styles.css" />zip (iter1 iter2) | <templatestyles src="Mono/styles.css" />zip (iter1 iter2 iter3) | <templatestyles src="Mono/styles.css" />zip (iter1 ... itern) | The shape of each iterator, the rank and the extents in each dimension, must be identical.[4] |
| Clojure | <templatestyles src="Mono/styles.css" />Template:Codett list1 list2) <templatestyles src="Mono/styles.css" />Template:Codett list1 list2) |
<templatestyles src="Mono/styles.css" />Template:Codett list1 list2 list3) <templatestyles src="Mono/styles.css" />Template:Codett list1 list2 list3) |
<templatestyles src="Mono/styles.css" />Template:Codett list1 … listn) <templatestyles src="Mono/styles.css" />Template:Codett list1 … listn) |
Stops after the length of the shortest list. |
| Common Lisp | Template:Codett | Template:Codett | Template:Codett | Stops after the length of the shortest list. |
| D | <templatestyles src="Mono/styles.css" />zip(range1, range2) <templatestyles src="Mono/styles.css" />range1.zip(range2) |
<templatestyles src="Mono/styles.css" />zip(range1, range2,range3) <templatestyles src="Mono/styles.css" />range1.zip(range2, range3) |
<templatestyles src="Mono/styles.css" />zip(range1, …, rangeN) <templatestyles src="Mono/styles.css" />range1.zip(…, rangeN) |
The stopping policy defaults to shortest and can be optionally provided as shortest, longest, or requiring the same length.[5] The second form is an example of UFCS. |
| F# | <templatestyles src="Mono/styles.css" />List.zip list1 list2 <templatestyles src="Mono/styles.css" />Seq.zip source1 source2 <templatestyles src="Mono/styles.css" />Array.zip array1 array2 |
<templatestyles src="Mono/styles.css" />List.zip3 list1 list2 list3 <templatestyles src="Mono/styles.css" />Seq.zip3 source1 source2 source3 <templatestyles src="Mono/styles.css" />Array.zip3 array1 array2 array3 |
||
| Haskell | <templatestyles src="Mono/styles.css" />zip list1 list2 | <templatestyles src="Mono/styles.css" />zip3 list1 list2 list3 | <templatestyles src="Mono/styles.css" />zipn list1 … listn | <templatestyles src="Mono/styles.css" />zipn for n > 3 is available in the module Data.List. Stops after the shortest list ends. |
| Python | <templatestyles src="Mono/styles.css" />zip(list1, list2) | <templatestyles src="Mono/styles.css" />zip(list1, list2, list3) | <templatestyles src="Mono/styles.css" />zip(list1, …, listn) | <templatestyles src="Mono/styles.css" />zip() and <templatestyles src="Mono/styles.css" />map() (3.x) stops after the shortest list ends, whereas <templatestyles src="Mono/styles.css" />map() (2.x) and <templatestyles src="Mono/styles.css" />itertools.zip_longest() (3.x) extends the shorter lists with <templatestyles src="Mono/styles.css" />None items |
| Ruby | <templatestyles src="Mono/styles.css" />list1.zip(list2) | <templatestyles src="Mono/styles.css" />list1.zip(list2, list3) | <templatestyles src="Mono/styles.css" />list1.zip(list1, .., listn) | When the list being executed upon (list1) is shorter than the lists being zipped the resulting list is the length of list1. If list1 is longer nil values are used to fill the missing values[6] |
| Scala | <templatestyles src="Mono/styles.css" />list1.zip(list2) | If one of the two collections is longer than the other, its remaining elements are ignored.[7] |
| Language | Unzip | Unzip 3 tuples | Unzip n tuples | Notes |
|---|---|---|---|---|
| Clojure | <templatestyles src="Mono/styles.css" />Template:Codett ziplist) | <templatestyles src="Mono/styles.css" />Template:Codett ziplist) | <templatestyles src="Mono/styles.css" />Template:Codett ziplist) | |
| Common Lisp | Template:Codett | Template:Codett | Template:Codett | |
| F# | <templatestyles src="Mono/styles.css" />List.unzip list1 list2 <templatestyles src="Mono/styles.css" />Seq.unzip source1 source2 <templatestyles src="Mono/styles.css" />Array.unzip array1 array2 |
<templatestyles src="Mono/styles.css" />List.unzip3 list1 list2 list3 <templatestyles src="Mono/styles.css" />Seq.unzip3 source1 source2 source3 <templatestyles src="Mono/styles.css" />Array.unzip3 array1 array2 array3 |
||
| Haskell | <templatestyles src="Mono/styles.css" />unzip ziplist | <templatestyles src="Mono/styles.css" />unzip3 ziplist | <templatestyles src="Mono/styles.css" />unzipn ziplist | <templatestyles src="Mono/styles.css" />unzipn for n > 3 is available in the module <templatestyles src="Mono/styles.css" />Data.List. |
| Python | <templatestyles src="Mono/styles.css" />zip(*zipvlist) | <templatestyles src="Mono/styles.css" />zip(*zipvlist) | <templatestyles src="Mono/styles.css" />zip(*zipvlist) |
See also
Script error: No such module "Portal".
References
- ↑ map from ClojureDocs
- ↑ a b map(function, iterable, ...) from section Built-in Functions from Python v2.7.2 documentation
- ↑ zip :: [a] -> [b] -> [(a, b)] from Prelude, Basic libraries
- ↑ Script error: No such module "citation/CS1".
- ↑ Script error: No such module "citation/CS1".
- ↑ Script error: No such module "citation/CS1".
- ↑ Script error: No such module "citation/CS1".