@@ -22,7 +22,9 @@ import .Base:
22
22
getindex, setindex!, get, iterate,
23
23
popfirst!, isdone, peek
24
24
25
- export enumerate, zip, rest, countfrom, take, drop, takewhile, dropwhile, cycle, repeated, product, flatten, partition
25
+ export enumerate, zip, unzip,
26
+ rest, countfrom, take, drop, takewhile, dropwhile,
27
+ cycle, repeated, product, flatten, partition
26
28
27
29
tail_if_any (:: Tuple{} ) = ()
28
30
tail_if_any (x:: Tuple ) = tail (x)
@@ -390,6 +392,68 @@ _zip_iterator_eltype(::Type{Tuple{}}) = HasEltype()
390
392
391
393
reverse (z:: Zip ) = Zip (map (reverse, z. is))
392
394
395
+ # unzip
396
+
397
+ """
398
+ unzip(itrs) -> Vector{<:Vector}
399
+
400
+ The `unzip` function takes an iterator of iterators and returns a vector of
401
+ vectors such that the first vector contains the first element yielded by each
402
+ iterator, the second vector the second element yielded by each iterator, etc.
403
+ `unzip` is sort of an inverse to the `zip` operation, as the name suggests.
404
+ In particular, if we define
405
+
406
+ ≐(a, b) = collect(collect.(a)) == collect(collect.(b))
407
+
408
+ then the following identities relating `zip` and `unzip` hold for any `itrs`
409
+ that is is an iterator of iterators:
410
+
411
+ unzip(zip(itrs...)) ≐ itrs
412
+ zip(unzip(itrs)...) ≐ itrs
413
+
414
+ Note that `unzip` does not return an iterator: it always consumes all of
415
+ its argument and all of each iterator yielded by its argument. It is only
416
+ associated with iteration because it is the inverse of `zip`.
417
+
418
+ # Examples
419
+
420
+ ```jldoctest
421
+ julia> unzip(enumerate("Hello"))
422
+ 2-element Array{Array{T,1} where T,1}:
423
+ [1, 2, 3]
424
+ ['a', 'b', 'c']
425
+
426
+ julia> unzip([[1, 'a'], [2.5, 'z'], [0, 'x']])
427
+ 2-element Array{Array{T,1} where T,1}:
428
+ Real[1, 2.5, 0]
429
+ ['a', 'z', 'x']
430
+ ```
431
+ """
432
+ function unzip (itrs)
433
+ n = Base. haslength (itrs) ? length (itrs) : - 1
434
+ vecs = Vector[]
435
+ for itr in itrs
436
+ for (j, x) in enumerate (itr)
437
+ if length (vecs) < j
438
+ v = [x]
439
+ push! (vecs, v)
440
+ n ≥ 0 && sizehint! (v, n)
441
+ else
442
+ v = vecs[j]
443
+ if ! (x isa eltype (v))
444
+ T = Base. promote_typejoin (typeof (x), eltype (v))
445
+ v = vecs[j] = copyto! (similar (v, T), v)
446
+ n ≥ 0 && sizehint! (v, n)
447
+ end
448
+ push! (v, x)
449
+ end
450
+ end
451
+ length (first (vecs)) == length (last (vecs)) ||
452
+ throw (ArgumentError (" unzip called with uneven iterators" ))
453
+ end
454
+ return vecs
455
+ end
456
+
393
457
# filter
394
458
395
459
struct Filter{F,I}
0 commit comments